FormLabelPrint.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. using qdr.app.studiou.orders2printpack.Extensions;
  2. using qdr.app.studiou.orders2printpack.Labels;
  3. using qdr.app.studiou.orders2printpack.Properties;
  4. using System.Data;
  5. using System.IO.Abstractions;
  6. namespace qdr.app.studiou.orders2printpack
  7. {
  8. public partial class FormLabelPrint : Form
  9. {
  10. private string? _csvPath;
  11. private string? _xlsPath;
  12. private DataTable? _data;
  13. public FormLabelPrint()
  14. {
  15. InitializeComponent();
  16. }
  17. #region *** Form Handlers ***
  18. private void butOpenCsv_Click(object sender, EventArgs e)
  19. {
  20. BlockErrorHandled(() =>
  21. {
  22. if (dlgOpenCsv.ShowDialog(this) == DialogResult.OK)
  23. {
  24. _csvPath = dlgOpenCsv.FileName;
  25. tbCsvPath.Text = _csvPath;
  26. _data = CsvUtils.CsvToDataTable(new FileSystem(), _csvPath, AppSettings.Default.CSVDelimiter );
  27. RefreshParameters();
  28. }
  29. });
  30. }
  31. private void butOpenXls_Click(object sender, EventArgs e)
  32. {
  33. BlockErrorHandled(() =>
  34. {
  35. if (dlgSaveXls.ShowDialog(this) == DialogResult.OK)
  36. {
  37. _xlsPath = dlgSaveXls.FileName;
  38. tbXslxPath.Text = _xlsPath;
  39. }
  40. });
  41. }
  42. private void butGenerate_Click(object sender, EventArgs e)
  43. {
  44. BlockErrorHandled(() =>
  45. {
  46. if (string.IsNullOrEmpty(_csvPath)) throw new Exception($"Vstupní CSV soubor musí být vybrán.");
  47. if (string.IsNullOrEmpty(_xlsPath)) throw new Exception($"Výstupní XSLX soubor musí být vybrán.");
  48. if (!File.Exists(_csvPath)) throw new Exception($"Vstupní CSV soubor '{_csvPath}' neexistuje, vyberte existující soubor.");
  49. if (_data == null) throw new Exception($"Vstupní CSV soubor '{_csvPath}' musí být otevřen.");
  50. _data = ProcessData(_data);
  51. var generator = new ExcelLabelGenerator(AppSettings.Default.LabelTemplate.Replace("{cr}","\n"));
  52. if (generator.GenerateLabels(_data, _xlsPath, int.Parse(AppSettings.Default.LabelPerRow), int.Parse(AppSettings.Default.LabelPerCol), double.Parse(AppSettings.Default.LabelWidth), double.Parse(AppSettings.Default.LabelHeight)))
  53. MessageBox.Show(this, $"Výstupní soubor '{_xlsPath}' byl vygenerován.", "Export", MessageBoxButtons.OK, MessageBoxIcon.Information);
  54. RefreshParameters();
  55. });
  56. }
  57. private DataTable ProcessData(DataTable data)
  58. {
  59. // Aggregate data first
  60. data = AggregateData(data);
  61. var expressionParts = AppSettings.Default.LabelAggegationDataExpression.Split('=');
  62. var expressionColumnName = expressionParts[0];
  63. var expressionValue = expressionParts[1];
  64. data.Columns.Add(expressionColumnName, typeof(string));
  65. var result = data.Clone();
  66. result.Rows.Clear();
  67. foreach (DataRow row in data.Rows)
  68. {
  69. var rowNew = result.Select($"order_no = '{row["order_no"]}' AND prod_cat = '{row["prod_cat"]}'");
  70. if (rowNew.Length == 0)
  71. {
  72. var newRow = result.NewRow();
  73. newRow.ItemArray = row.ItemArray.ToArray();
  74. newRow[expressionColumnName] = expressionValue.Replace("{prod_var_type}", row["prod_var_type"].ToString())
  75. .Replace("{qty}",row["qty"].ToString()).Replace("{cr}","\n");
  76. result.Rows.Add(newRow);
  77. }
  78. else
  79. {
  80. rowNew[0][expressionColumnName] = rowNew[0][expressionColumnName] + expressionValue.Replace("{prod_var_type}", row["prod_var_type"].ToString())
  81. .Replace("{qty}", row["qty"].ToString()).Replace("{cr}", "\n");
  82. }
  83. }
  84. return result;
  85. }
  86. /// <summary>
  87. /// Aggregates order data by grouping order numbers, product categories, and product variant types,
  88. /// then summing the quantities for each group.
  89. /// </summary>
  90. /// <param name="data">Input DataTable containing order details</param>
  91. /// <returns>Aggregated DataTable with columns: order_no, prod_cat, prod_var_type, qty (sum)</returns>
  92. private DataTable AggregateData(DataTable data)
  93. {
  94. if (data == null)
  95. throw new ArgumentNullException(nameof(data));
  96. // Create result DataTable with appropriate columns
  97. DataTable result = new DataTable();
  98. result.Columns.Add("order_no", typeof(string));
  99. result.Columns.Add("email", typeof(string));
  100. result.Columns.Add("prod_cat", typeof(string));
  101. result.Columns.Add("prod_var_type", typeof(string));
  102. result.Columns.Add("qty", typeof(string));
  103. // Group and aggregate using LINQ
  104. var aggregatedData = data.AsEnumerable()
  105. .GroupBy(row => new
  106. {
  107. OrderNo = row.Field<string>("order_no"),
  108. Email = row.Field<string>("email"),
  109. ProdCat = row.Field<string>("prod_cat"),
  110. ProdVarType = row.Field<string>("prod_var_type")
  111. })
  112. .Select(group => new
  113. {
  114. group.Key.OrderNo,
  115. group.Key.Email,
  116. group.Key.ProdCat,
  117. group.Key.ProdVarType,
  118. TotalQty = group.Sum(row => int.Parse(row.Field<string>("qty"))).ToString()
  119. })
  120. .OrderBy(x => x.OrderNo)
  121. .ThenBy(x => x.ProdCat)
  122. .ThenBy(x => x.ProdVarType);
  123. // Populate result DataTable
  124. foreach (var item in aggregatedData)
  125. {
  126. result.Rows.Add(
  127. item.OrderNo,
  128. item.Email,
  129. item.ProdCat,
  130. item.ProdVarType,
  131. int.Parse(item.TotalQty)
  132. );
  133. }
  134. return result;
  135. }
  136. private void butConfig_Click(object sender, EventArgs e)
  137. {
  138. var dlg = new dlgLabelSettings();
  139. if (dlg.ShowDialog(this) == DialogResult.OK)
  140. {
  141. // Save settings
  142. RefreshParameters();
  143. }
  144. }
  145. private void butClose_Click(object sender, EventArgs e)
  146. {
  147. Close();
  148. }
  149. #endregion
  150. #region *** Private Methods ***
  151. private void RefreshParameters()
  152. {
  153. lParCount.Text = $"Štítků/záznamů: {_data?.Rows.Count}";
  154. lParCol.Text = $"Štítků ve sloupci: {AppSettings.Default.LabelPerCol}";
  155. lParRow.Text = $"Štítků řádků na stránku: {AppSettings.Default.LabelPerRow}";
  156. }
  157. private void BlockErrorHandled(Action block)
  158. {
  159. try
  160. {
  161. block();
  162. }
  163. catch (Exception ex)
  164. {
  165. // Log("Error: " + ex.Message);
  166. MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
  167. }
  168. }
  169. #endregion
  170. #region *** Nested classes ***
  171. #endregion
  172. }
  173. }