using OfficeOpenXml.Style; using OfficeOpenXml; using Sunny.UI; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using 鲁尔圆锥接头测试仪.Data; using static 鲁尔圆锥接头测试仪.SeparatTest; namespace 鲁尔圆锥接头测试仪 { public partial class SeparatReport : UIForm { private main _main; private TestScreen _TestScreen; private DebugScreen _DebugScreen; private SeparatTest _SeparartTest; //private SeparatReport _SeparatReport; protected List reports; public SeparatReport(List reports) { InitializeComponent(); this.reports = reports; } private void SeparatReport_Load(object sender, EventArgs e) { uiDataGridView1.DataSource = reports; AdjustDataGridViewStyle(); } private void SwitchWindow(ref T windowInstance, Func createFunc) where T : UIForm { // 3. 复用窗口实例:不存在则创建,存在则激活 if (windowInstance == null) { windowInstance = createFunc(); windowInstance.Closed += (s, args) => { this.Activate(); }; } else { // 激活已存在的窗口(前置显示) windowInstance.Activate(); return; } this.Hide(); windowInstance.Show(); } private void SeparatReport_FormClosing(object sender, FormClosingEventArgs e) { // 释放Modbus资源 ModbusResourceManager.Instance?.Dispose(); // 确保应用程序完全退出 Application.Exit(); } private void SeparatReport_FormClosed(object sender, FormClosedEventArgs e) { //_SeparatReport?.Close(); reports?.Clear(); } private void Btn_home_Click(object sender, EventArgs e) { SwitchWindow(ref _main, () => new main()); } private void Btn_testscreen_Click(object sender, EventArgs e) { SwitchWindow(ref _TestScreen, () => new TestScreen()); } private void Btn_debug_Click(object sender, EventArgs e) { SwitchWindow(ref _DebugScreen, () => new DebugScreen()); } private void Btn_return_Click(object sender, EventArgs e) { SwitchWindow(ref _SeparartTest, () => new SeparatTest()); } private void Btn_clear_Click(object sender, EventArgs e) { DialogResult result = MessageBox.Show( "确定要清空所有记录吗?此操作不可恢复!", "确认清空", MessageBoxButtons.YesNo, MessageBoxIcon.Warning ); if (result == DialogResult.Yes) { try { reports.Clear(); uiDataGridView1.DataSource = new List(); MessageBox.Show( "记录已清空", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information ); } catch (Exception ex) { MessageBox.Show( $"清空失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error ); } } } private void ExportButton_Click(object sender, EventArgs e) { try { using (SaveFileDialog saveDialog = new SaveFileDialog()) { saveDialog.Filter = "Excel文件|*.xlsx|CSV文件|*.csv|PDF文件|*.pdf"; saveDialog.Title = "导出报表"; saveDialog.FileName = $"分离力记录报告_{DateTime.Now:yyyyMMdd_HHmmss}"; if (saveDialog.ShowDialog() == DialogResult.OK) { string filePath = saveDialog.FileName; ExportToExcel(filePath); } } } catch (Exception ex) { ShowMessage("导出错误", $"导出失败:{ex.Message}", UIMessageBoxIcon.Error); } } private void AdjustDataGridViewStyle() { foreach (DataGridViewColumn column in uiDataGridView1.Columns) { // 自动调整列宽(适配内容) column.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; // 列宽最小值(防止过窄) if (column.Width < 120) column.Width = 120; // 单元格内容居中 column.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; column.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter; } } private void ExportToExcel(string filePath) { try { string extension = Path.GetExtension(filePath).ToLower(); // 根据文件后缀分支处理 switch (extension) { case ".xlsx": ExportToXlsx(filePath); // Excel格式(支持样式) break; case ".csv": ExportToCsv(filePath); // CSV格式(基础导出) break; case ".pdf": ShowMessage("提示", "PDF导出暂未实现,已自动切换为Excel格式", UIMessageBoxIcon.Info); ExportToXlsx(Path.ChangeExtension(filePath, ".xlsx")); filePath = Path.ChangeExtension(filePath, ".xlsx"); break; default: throw new NotSupportedException("不支持的文件格式!"); } ShowMessage("导出成功", $"报表已成功导出到:{filePath}", UIMessageBoxIcon.Success); } catch (Exception ex) { ShowMessage("导出错误", $"导出失败:{ex.Message}", UIMessageBoxIcon.Error); } } /// /// 导出为Excel(.xlsx),支持列宽调整+居中样式 /// private void ExportToXlsx(string filePath) { // 授权EPPlus使用(非商业用途) ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial; using (var package = new ExcelPackage()) { var worksheet = package.Workbook.Worksheets.Add("漏液记录报告"); // 找到化验编号输入文本框 //var labNumberInput = this.Controls.OfType() // .FirstOrDefault(tb => tb.Location.X == uiDataGridView1.Width - 130 && tb.ReadOnly == false); //string labNumberValue = labNumberInput?.Text?.Trim() ?? "未填写"; // 1. 写入化验编号(第1行) //worksheet.Cells["A1"].Value = "化验编号"; //worksheet.Cells["B1"].Value = labNumberValue; // 合并单元格(美化) //worksheet.Cells["A1:B1"].Style.Font.Bold = true; //worksheet.Cells["A1:B1"].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; // 2. 写入表头(第3行,空出第2行分隔) int headerRow = 1; for (int i = 0; i < uiDataGridView1.Columns.Count; i++) { worksheet.Cells[headerRow, i + 1].Value = uiDataGridView1.Columns[i].HeaderText; // 表头样式:加粗+居中 worksheet.Cells[headerRow, i + 1].Style.Font.Bold = true; worksheet.Cells[headerRow, i + 1].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; worksheet.Cells[headerRow, i + 1].Style.VerticalAlignment = ExcelVerticalAlignment.Center; } // 3. 写入数据行 int dataRow = headerRow + 1; foreach (DataGridViewRow row in uiDataGridView1.Rows) { if (!row.IsNewRow) { for (int i = 0; i < row.Cells.Count; i++) { string cellValue = row.Cells[i].Value?.ToString() ?? ""; cellValue = cellValue.Replace("\n", " ").Replace("\r", " ").Trim(); worksheet.Cells[dataRow, i + 1].Value = cellValue; // 数据居中 worksheet.Cells[dataRow, i + 1].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; worksheet.Cells[dataRow, i + 1].Style.VerticalAlignment = ExcelVerticalAlignment.Center; // 日期列特殊处理(确保格式完整) if (uiDataGridView1.Columns[i].HeaderText.Contains("时间") || uiDataGridView1.Columns[i].HeaderText.Contains("日期")) { worksheet.Cells[dataRow, i + 1].Style.Numberformat.Format = "yyyy-MM-dd HH:mm:ss"; } } dataRow++; } } // 4. 自动调整列宽(关键:解决日期显示不完整) for (int i = 1; i <= uiDataGridView1.Columns.Count; i++) { // 自动适配内容宽度,最小值15(Excel列宽单位) worksheet.Column(i).AutoFit(); if (worksheet.Column(i).Width < 15) { worksheet.Column(i).Width = 15; } // 日期列强制加宽(避免仍截断) if (worksheet.Cells[headerRow, i].Value?.ToString().Contains("时间") == true || worksheet.Cells[headerRow, i].Value?.ToString().Contains("日期") == true) { worksheet.Column(i).Width = 25; } } // 5. 保存文件 package.SaveAs(new FileInfo(filePath)); } } private void ShowMessage(string title, string message, UIMessageBoxIcon icon) { switch (icon) { case UIMessageBoxIcon.Success: UIMessageTip.ShowOk(message); break; case UIMessageBoxIcon.Error: UIMessageTip.ShowError(message); break; case UIMessageBoxIcon.Info: UIMessageTip.ShowWarning(message); break; default: UIMessageBox.Show(message, title); break; } } private void ExportToCsv(string filePath) { var labNumberInput = this.Controls.OfType() .FirstOrDefault(tb => tb.Location.X == uiDataGridView1.Width - 130 && tb.ReadOnly == false); string labNumberValue = labNumberInput?.Text?.Trim() ?? "未填写"; using (var writer = new StreamWriter(filePath, false, System.Text.Encoding.UTF8)) { writer.Write('\uFEFF'); writer.WriteLine(); // 空行分隔 // 写入表头 var headerCells = new List(); foreach (DataGridViewColumn column in uiDataGridView1.Columns) { headerCells.Add(EscapeCsv(column.HeaderText)); } writer.WriteLine(string.Join(",", headerCells)); // 写入数据 foreach (DataGridViewRow row in uiDataGridView1.Rows) { if (!row.IsNewRow) { var cells = new List(); foreach (DataGridViewCell cell in row.Cells) { string cellValue = cell.Value?.ToString() ?? ""; cellValue = cellValue.Replace("\n", " ").Replace("\r", " ").Trim(); cells.Add(EscapeCsv(cellValue)); } writer.WriteLine(string.Join(",", cells)); } } } // 提示CSV样式调整方法 ShowMessage("提示", "CSV文件导出成功!打开后可手动设置:\n1. 选中列 → 右键 → 列宽(建议日期列设为20)\n2. 选中单元格 → 开始 → 居中对齐", UIMessageBoxIcon.Info); } private string EscapeCsv(string value) { if (string.IsNullOrEmpty(value)) return ""; if (value.Contains(",") || value.Contains("\"") || value.Contains("\n") || value.Contains("\r") || value.Contains(",")) { value = value.Replace("\"", "\"\""); return $"\"{value}\""; } return value; } } }