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
}
}