using qdr.app.studiou.orders2printpack.Extensions; using qdr.app.studiou.orders2printpack.Labels; using qdr.app.studiou.orders2printpack.Properties; using System.Data; using System.IO.Abstractions; namespace qdr.app.studiou.orders2printpack { public partial class FormLabelPrint : Form { private string? _csvPath; private string? _xlsPath; private DataTable? _data; public FormLabelPrint() { InitializeComponent(); } #region *** Form Handlers *** private void butOpenCsv_Click(object sender, EventArgs e) { BlockErrorHandled(() => { if (dlgOpenCsv.ShowDialog(this) == DialogResult.OK) { _csvPath = dlgOpenCsv.FileName; tbCsvPath.Text = _csvPath; _data = CsvUtils.CsvToDataTable(new FileSystem(), _csvPath, AppSettings.Default.CSVDelimiter ); RefreshParameters(); } }); } private void butOpenXls_Click(object sender, EventArgs e) { BlockErrorHandled(() => { if (dlgSaveXls.ShowDialog(this) == DialogResult.OK) { _xlsPath = dlgSaveXls.FileName; tbXslxPath.Text = _xlsPath; } }); } private void butGenerate_Click(object sender, EventArgs e) { BlockErrorHandled(() => { if (string.IsNullOrEmpty(_csvPath)) throw new Exception($"Vstupní CSV soubor musí být vybrán."); if (string.IsNullOrEmpty(_xlsPath)) throw new Exception($"Výstupní XSLX soubor musí být vybrán."); if (!File.Exists(_csvPath)) throw new Exception($"Vstupní CSV soubor '{_csvPath}' neexistuje, vyberte existující soubor."); if (_data == null) throw new Exception($"Vstupní CSV soubor '{_csvPath}' musí být otevřen."); _data = ProcessData(_data); var generator = new ExcelLabelGenerator(AppSettings.Default.LabelTemplate.Replace("{cr}","\n")); 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))) MessageBox.Show(this, $"Výstupní soubor '{_xlsPath}' byl vygenerován.", "Export", MessageBoxButtons.OK, MessageBoxIcon.Information); RefreshParameters(); }); } private DataTable ProcessData(DataTable data) { // Aggregate data first data = AggregateData(data); var expressionParts = AppSettings.Default.LabelAggegationDataExpression.Split('='); var expressionColumnName = expressionParts[0]; var expressionValue = expressionParts[1]; data.Columns.Add(expressionColumnName, typeof(string)); var result = data.Clone(); result.Rows.Clear(); foreach (DataRow row in data.Rows) { var rowNew = result.Select($"order_no = '{row["order_no"]}' AND prod_cat = '{row["prod_cat"]}'"); if (rowNew.Length == 0) { var newRow = result.NewRow(); newRow.ItemArray = row.ItemArray.ToArray(); newRow[expressionColumnName] = expressionValue.Replace("{prod_var_type}", row["prod_var_type"].ToString()) .Replace("{qty}",row["qty"].ToString()).Replace("{cr}","\n"); result.Rows.Add(newRow); } else { rowNew[0][expressionColumnName] = rowNew[0][expressionColumnName] + expressionValue.Replace("{prod_var_type}", row["prod_var_type"].ToString()) .Replace("{qty}", row["qty"].ToString()).Replace("{cr}", "\n"); } } return result; } /// /// Aggregates order data by grouping order numbers, product categories, and product variant types, /// then summing the quantities for each group. /// /// Input DataTable containing order details /// Aggregated DataTable with columns: order_no, prod_cat, prod_var_type, qty (sum) private DataTable AggregateData(DataTable data) { if (data == null) throw new ArgumentNullException(nameof(data)); // Create result DataTable with appropriate columns DataTable result = new DataTable(); result.Columns.Add("order_no", typeof(string)); result.Columns.Add("email", typeof(string)); result.Columns.Add("prod_cat", typeof(string)); result.Columns.Add("prod_var_type", typeof(string)); result.Columns.Add("qty", typeof(string)); // Group and aggregate using LINQ var aggregatedData = data.AsEnumerable() .GroupBy(row => new { OrderNo = row.Field("order_no"), Email = row.Field("email"), ProdCat = row.Field("prod_cat"), ProdVarType = row.Field("prod_var_type") }) .Select(group => new { group.Key.OrderNo, group.Key.Email, group.Key.ProdCat, group.Key.ProdVarType, TotalQty = group.Sum(row => int.Parse(row.Field("qty"))).ToString() }) .OrderBy(x => x.OrderNo) .ThenBy(x => x.ProdCat) .ThenBy(x => x.ProdVarType); // Populate result DataTable foreach (var item in aggregatedData) { result.Rows.Add( item.OrderNo, item.Email, item.ProdCat, item.ProdVarType, int.Parse(item.TotalQty) ); } return result; } private void butConfig_Click(object sender, EventArgs e) { var dlg = new dlgLabelSettings(); if (dlg.ShowDialog(this) == DialogResult.OK) { // Save settings RefreshParameters(); } } private void butClose_Click(object sender, EventArgs e) { Close(); } #endregion #region *** Private Methods *** private void RefreshParameters() { lParCount.Text = $"Štítků/záznamů: {_data?.Rows.Count}"; lParCol.Text = $"Štítků ve sloupci: {AppSettings.Default.LabelPerCol}"; lParRow.Text = $"Štítků řádků na stránku: {AppSettings.Default.LabelPerRow}"; } private void BlockErrorHandled(Action block) { try { block(); } catch (Exception ex) { // Log("Error: " + ex.Message); MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } #endregion #region *** Nested classes *** #endregion } }