FormLabelPrint.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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("prod_cat", typeof(string));
  100. result.Columns.Add("prod_var_type", typeof(string));
  101. result.Columns.Add("qty", typeof(string));
  102. // Group and aggregate using LINQ
  103. var aggregatedData = data.AsEnumerable()
  104. .GroupBy(row => new
  105. {
  106. OrderNo = row.Field<string>("order_no"),
  107. ProdCat = row.Field<string>("prod_cat"),
  108. ProdVarType = row.Field<string>("prod_var_type")
  109. })
  110. .Select(group => new
  111. {
  112. group.Key.OrderNo,
  113. group.Key.ProdCat,
  114. group.Key.ProdVarType,
  115. TotalQty = group.Sum(row => int.Parse(row.Field<string>("qty"))).ToString()
  116. })
  117. .OrderBy(x => x.OrderNo)
  118. .ThenBy(x => x.ProdCat)
  119. .ThenBy(x => x.ProdVarType);
  120. // Populate result DataTable
  121. foreach (var item in aggregatedData)
  122. {
  123. result.Rows.Add(
  124. item.OrderNo,
  125. item.ProdCat,
  126. item.ProdVarType,
  127. int.Parse(item.TotalQty)
  128. );
  129. }
  130. return result;
  131. }
  132. private void butConfig_Click(object sender, EventArgs e)
  133. {
  134. var dlg = new dlgLabelSettings();
  135. if (dlg.ShowDialog(this) == DialogResult.OK)
  136. {
  137. // Save settings
  138. RefreshParameters();
  139. }
  140. }
  141. private void butClose_Click(object sender, EventArgs e)
  142. {
  143. Close();
  144. }
  145. #endregion
  146. #region *** Private Methods ***
  147. private void RefreshParameters()
  148. {
  149. lParCount.Text = $"Štítků/záznamů: {_data?.Rows.Count}";
  150. lParCol.Text = $"Štítků ve sloupci: {AppSettings.Default.LabelPerCol}";
  151. lParRow.Text = $"Štítků řádků na stránku: {AppSettings.Default.LabelPerRow}";
  152. }
  153. private void BlockErrorHandled(Action block)
  154. {
  155. try
  156. {
  157. block();
  158. }
  159. catch (Exception ex)
  160. {
  161. // Log("Error: " + ex.Message);
  162. MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
  163. }
  164. }
  165. #endregion
  166. #region *** Nested classes ***
  167. #endregion
  168. }
  169. }