using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.IO.Ports;
using System.IO;
using System.Globalization;
using System.Data;
using System.Windows.Forms.DataVisualization.Charting;
using OfficeOpenXml;
using OfficeOpenXml.Style;
using OfficeOpenXml.Drawing.Chart;
namespace PhysicsExperimentDisplay
{
public partial class MainForm : Form
{
// 控件声明
private TableLayoutPanel mainLayout;
private GroupBox gbSerial;
private ComboBox cmbPorts;
private ComboBox cmbBaudRate;
private Button btnConnect;
private Label lblPort;
private Label lblBaud;
private GroupBox gbData;
private DataGridView dgvResults;
private GroupBox gbChart;
private Button btnExport;
private Button btnClear;
private SerialPort serialPort;
private FlowLayoutPanel buttonPanel;
private TableLayoutPanel serialLayout;
private Chart chartPlot;
// 数据存储 private List<double> accelerationData = new List<double>(); private int dataPointCount = 0; private DataGridViewTextBoxColumn Time; private DataGridViewTextBoxColumn T1; private DataGridViewTextBoxColumn T2; private DataGridViewTextBoxColumn V1; private DataGridViewTextBoxColumn V2; private DataGridViewTextBoxColumn Acc; private DateTime experimentStartTime = DateTime.Now; public MainForm() { InitializeComponent(); LoadAvailablePorts(); InitializePlot(); // 绑定按钮事件 btnConnect.Click += btnConnect_Click; btnExport.Click += btnExport_Click; btnClear.Click += btnClear_Click; } private void InitializeComponent() { this.mainLayout = new System.Windows.Forms.TableLayoutPanel(); this.gbSerial = new System.Windows.Forms.GroupBox(); this.serialLayout = new System.Windows.Forms.TableLayoutPanel(); this.lblPort = new System.Windows.Forms.Label(); this.cmbPorts = new System.Windows.Forms.ComboBox(); this.lblBaud = new System.Windows.Forms.Label(); this.cmbBaudRate = new System.Windows.Forms.ComboBox(); this.btnConnect = new System.Windows.Forms.Button(); this.buttonPanel = new System.Windows.Forms.FlowLayoutPanel(); this.btnExport = new System.Windows.Forms.Button(); this.btnClear = new System.Windows.Forms.Button(); this.gbData = new System.Windows.Forms.GroupBox(); this.dgvResults = new System.Windows.Forms.DataGridView(); this.Time = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.T1 = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.T2 = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.V1 = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.V2 = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.Acc = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.gbChart = new System.Windows.Forms.GroupBox(); this.chartPlot = new System.Windows.Forms.DataVisualization.Charting.Chart(); this.mainLayout.SuspendLayout(); this.gbSerial.SuspendLayout(); this.serialLayout.SuspendLayout(); this.buttonPanel.SuspendLayout(); this.gbData.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.dgvResults)).BeginInit(); this.gbChart.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.chartPlot)).BeginInit(); this.SuspendLayout(); // // mainLayout // this.mainLayout.ColumnCount = 1; this.mainLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.mainLayout.Controls.Add(this.gbSerial, 0, 0); this.mainLayout.Controls.Add(this.buttonPanel, 0, 1); this.mainLayout.Controls.Add(this.gbData, 0, 2); this.mainLayout.Controls.Add(this.gbChart, 0, 3); this.mainLayout.Dock = System.Windows.Forms.DockStyle.Fill; this.mainLayout.Location = new System.Drawing.Point(0, 0); this.mainLayout.Name = "mainLayout"; this.mainLayout.Padding = new System.Windows.Forms.Padding(10); this.mainLayout.RowCount = 4; this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 100F)); this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 40F)); this.mainLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 60F)); this.mainLayout.Size = new System.Drawing.Size(1178, 744); this.mainLayout.TabIndex = 0; // // gbSerial // this.gbSerial.Controls.Add(this.serialLayout); this.gbSerial.Dock = System.Windows.Forms.DockStyle.Fill; this.gbSerial.Location = new System.Drawing.Point(13, 13); this.gbSerial.Name = "gbSerial"; this.gbSerial.Size = new System.Drawing.Size(1152, 94); this.gbSerial.TabIndex = 0; this.gbSerial.TabStop = false; this.gbSerial.Text = "串口设置"; // // serialLayout // this.serialLayout.ColumnCount = 4; this.serialLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 100F)); this.serialLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 30F)); this.serialLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 100F)); this.serialLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 30F)); this.serialLayout.Controls.Add(this.lblPort, 0, 0); this.serialLayout.Controls.Add(this.cmbPorts, 1, 0); this.serialLayout.Controls.Add(this.lblBaud, 2, 0); this.serialLayout.Controls.Add(this.cmbBaudRate, 3, 0); this.serialLayout.Controls.Add(this.btnConnect, 0, 1); this.serialLayout.Dock = System.Windows.Forms.DockStyle.Fill; this.serialLayout.Location = new System.Drawing.Point(3, 29); this.serialLayout.Name = "serialLayout"; this.serialLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.serialLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.serialLayout.Size = new System.Drawing.Size(1146, 62); this.serialLayout.TabIndex = 0; // // lblPort // this.lblPort.Location = new System.Drawing.Point(3, 0); this.lblPort.Name = "lblPort"; this.lblPort.Size = new System.Drawing.Size(94, 20); this.lblPort.TabIndex = 0; this.lblPort.Text = "串口号:"; this.lblPort.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // cmbPorts // this.cmbPorts.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cmbPorts.Font = new System.Drawing.Font("Consolas", 10F); this.cmbPorts.Location = new System.Drawing.Point(103, 3); this.cmbPorts.Name = "cmbPorts"; this.cmbPorts.Size = new System.Drawing.Size(121, 31); this.cmbPorts.TabIndex = 1; // // lblBaud // this.lblBaud.Location = new System.Drawing.Point(576, 0); this.lblBaud.Name = "lblBaud"; this.lblBaud.Size = new System.Drawing.Size(94, 20); this.lblBaud.TabIndex = 2; this.lblBaud.Text = "波特率:"; this.lblBaud.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // cmbBaudRate // this.cmbBaudRate.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cmbBaudRate.Font = new System.Drawing.Font("Consolas", 10F); this.cmbBaudRate.Location = new System.Drawing.Point(676, 3); this.cmbBaudRate.Name = "cmbBaudRate"; this.cmbBaudRate.Size = new System.Drawing.Size(121, 31); this.cmbBaudRate.TabIndex = 3; // // btnConnect // this.btnConnect.BackColor = System.Drawing.Color.LightGreen; this.serialLayout.SetColumnSpan(this.btnConnect, 4); this.btnConnect.Font = new System.Drawing.Font("Microsoft YaHei UI", 10F, System.Drawing.FontStyle.Bold); this.btnConnect.Location = new System.Drawing.Point(3, 23); this.btnConnect.Name = "btnConnect"; this.btnConnect.Size = new System.Drawing.Size(75, 23); this.btnConnect.TabIndex = 4; this.btnConnect.Text = "连接串口"; this.btnConnect.UseVisualStyleBackColor = false; // // buttonPanel // this.buttonPanel.Controls.Add(this.btnExport); this.buttonPanel.Controls.Add(this.btnClear); this.buttonPanel.Dock = System.Windows.Forms.DockStyle.Fill; this.buttonPanel.Location = new System.Drawing.Point(13, 113); this.buttonPanel.Name = "buttonPanel"; this.buttonPanel.Padding = new System.Windows.Forms.Padding(10, 0, 10, 0); this.buttonPanel.Size = new System.Drawing.Size(1152, 44); this.buttonPanel.TabIndex = 1; // // btnExport // this.btnExport.BackColor = System.Drawing.Color.LightBlue; this.btnExport.Location = new System.Drawing.Point(13, 3); this.btnExport.Name = "btnExport"; this.btnExport.Size = new System.Drawing.Size(180, 40); this.btnExport.TabIndex = 0; this.btnExport.Text = "导出数据(Excel)"; this.btnExport.UseVisualStyleBackColor = false; // // btnClear // this.btnClear.BackColor = System.Drawing.Color.LightSalmon; this.btnClear.Location = new System.Drawing.Point(199, 3); this.btnClear.Name = "btnClear"; this.btnClear.Size = new System.Drawing.Size(180, 40); this.btnClear.TabIndex = 1; this.btnClear.Text = "清除数据"; this.btnClear.UseVisualStyleBackColor = false; // // gbData // this.gbData.Controls.Add(this.dgvResults); this.gbData.Dock = System.Windows.Forms.DockStyle.Fill; this.gbData.Location = new System.Drawing.Point(13, 163); this.gbData.Name = "gbData"; this.gbData.Size = new System.Drawing.Size(1152, 223); this.gbData.TabIndex = 2; this.gbData.TabStop = false; this.gbData.Text = "实验数据"; // // dgvResults // this.dgvResults.AllowUserToAddRows = false; this.dgvResults.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill; this.dgvResults.BackgroundColor = System.Drawing.SystemColors.Window; this.dgvResults.BorderStyle = System.Windows.Forms.BorderStyle.None; this.dgvResults.ColumnHeadersHeight = 34; this.dgvResults.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { this.Time, this.T1, this.T2, this.V1, this.V2, this.Acc}); this.dgvResults.Dock = System.Windows.Forms.DockStyle.Fill; this.dgvResults.Location = new System.Drawing.Point(3, 29); this.dgvResults.Name = "dgvResults"; this.dgvResults.ReadOnly = true; this.dgvResults.RowHeadersVisible = false; this.dgvResults.RowHeadersWidth = 62; this.dgvResults.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; this.dgvResults.Size = new System.Drawing.Size(1146, 191); this.dgvResults.TabIndex = 0; // // Time // this.Time.HeaderText = "时间"; this.Time.MinimumWidth = 8; this.Time.Name = "Time"; this.Time.ReadOnly = true; // // T1 // this.T1.HeaderText = "T1(s)"; this.T1.MinimumWidth = 8; this.T1.Name = "T1"; this.T1.ReadOnly = true; // // T2 // this.T2.HeaderText = "T2(s)"; this.T2.MinimumWidth = 8; this.T2.Name = "T2"; this.T2.ReadOnly = true; // // V1 // this.V1.HeaderText = "V1(m/s)"; this.V1.MinimumWidth = 8; this.V1.Name = "V1"; this.V1.ReadOnly = true; // // V2 // this.V2.HeaderText = "V2(m/s)"; this.V2.MinimumWidth = 8; this.V2.Name = "V2"; this.V2.ReadOnly = true; // // Acc // this.Acc.HeaderText = "加速度(m/s²)"; this.Acc.MinimumWidth = 8; this.Acc.Name = "Acc"; this.Acc.ReadOnly = true; // // gbChart // this.gbChart.Controls.Add(this.chartPlot); this.gbChart.Dock = System.Windows.Forms.DockStyle.Fill; this.gbChart.Location = new System.Drawing.Point(13, 392); this.gbChart.Name = "gbChart"; this.gbChart.Size = new System.Drawing.Size(1152, 339); this.gbChart.TabIndex = 3; this.gbChart.TabStop = false; this.gbChart.Text = "加速度变化曲线"; // // chartPlot // this.chartPlot.Dock = System.Windows.Forms.DockStyle.Fill; this.chartPlot.Location = new System.Drawing.Point(3, 29); this.chartPlot.Name = "chartPlot"; this.chartPlot.Size = new System.Drawing.Size(1146, 307); this.chartPlot.TabIndex = 0; // // MainForm // this.ClientSize = new System.Drawing.Size(1178, 744); this.Controls.Add(this.mainLayout); this.Font = new System.Drawing.Font("Microsoft YaHei UI", 10F); this.Name = "MainForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "气垫导轨实验数据监控"; this.mainLayout.ResumeLayout(false); this.gbSerial.ResumeLayout(false); this.serialLayout.ResumeLayout(false); this.buttonPanel.ResumeLayout(false); this.gbData.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.dgvResults)).EndInit(); this.gbChart.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.chartPlot)).EndInit(); this.ResumeLayout(false); } // 初始化图表 private void InitializePlot() { // 清除现有图表区域和系列 chartPlot.ChartAreas.Clear(); chartPlot.Series.Clear(); chartPlot.Titles.Clear(); // 创建图表区域 ChartArea chartArea = new ChartArea("MainArea"); chartArea.AxisX.Title = "实验序号"; chartArea.AxisY.Title = "加速度 (m/s²)"; chartArea.AxisX.MajorGrid.LineColor = Color.LightGray; chartArea.AxisY.MajorGrid.LineColor = Color.LightGray; chartArea.AxisY.MajorGrid.LineDashStyle = ChartDashStyle.Dot; chartPlot.ChartAreas.Add(chartArea); // 创建数据系列 Series series = new Series("加速度"); series.ChartType = SeriesChartType.Line; series.Color = Color.Blue; series.BorderWidth = 2; series.MarkerStyle = MarkerStyle.Circle; series.MarkerSize = 8; series.MarkerColor = Color.DarkBlue; chartPlot.Series.Add(series); // 添加标题 Title title = new Title("加速度变化曲线", Docking.Top, new Font("Microsoft YaHei UI", 12, FontStyle.Bold), Color.Black); chartPlot.Titles.Add(title); // 初始化空数据点 series.Points.AddXY(0, 0); // 设置初始轴范围 chartArea.AxisX.Minimum = 0; chartArea.AxisX.Maximum = 10; chartArea.AxisY.Minimum = 0; chartArea.AxisY.Maximum = 10; } // 加载可用串口 private void LoadAvailablePorts() { cmbPorts.Items.Clear(); string[] ports = SerialPort.GetPortNames(); cmbPorts.Items.AddRange(ports); if (ports.Length > 0) cmbPorts.SelectedIndex = 0; // 设置波特率选项 cmbBaudRate.Items.AddRange(new object[] { 9600, 19200, 38400, 57600, 115200 }); cmbBaudRate.SelectedIndex = 4; // 默认115200 } // 连接/断开串口 private void btnConnect_Click(object sender, EventArgs e) { if (serialPort == null || !serialPort.IsOpen) { try { if (cmbPorts.SelectedItem == null) { MessageBox.Show("请选择有效的串口", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } serialPort = new SerialPort(cmbPorts.Text, (int)cmbBaudRate.SelectedItem); serialPort.DataReceived += SerialPort_DataReceived; serialPort.Open(); btnConnect.Text = "断开连接"; btnConnect.BackColor = Color.LightCoral; // 重置实验开始时间 experimentStartTime = DateTime.Now; } catch (Exception ex) { MessageBox.Show($"串口连接错误: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } else { try { serialPort.Close(); serialPort.Dispose(); serialPort = null; btnConnect.Text = "连接串口"; btnConnect.BackColor = Color.LightGreen; } catch (Exception ex) { MessageBox.Show($"断开连接错误: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } // 串口数据接收处理 private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { try { string data = serialPort.ReadLine(); this.Invoke(new Action(() => ProcessData(data))); } catch (Exception ex) { this.Invoke(new Action(() => MessageBox.Show($"数据接收错误: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error))); } } // 数据处理和显示 private void ProcessData(string rawData) { /* 数据格式示例: * "T1:0.025,T2:0.023,V1:0.4,V2:0.44,A:0.2" */ try { string[] pairs = rawData.Split(','); double t1 = 0, t2 = 0, v1 = 0, v2 = 0, acc = 0; foreach (string pair in pairs) { string[] keyValue = pair.Split(':'); if (keyValue.Length != 2) continue; switch (keyValue[0].Trim()) { case "T1": t1 = ParseDouble(keyValue[1]); break; case "T2": t2 = ParseDouble(keyValue[1]); break; case "V1": v1 = ParseDouble(keyValue[1]); break; case "V2": v2 = ParseDouble(keyValue[1]); break; case "A": acc = ParseDouble(keyValue[1]); break; } } // 计算相对时间(从实验开始) TimeSpan elapsed = DateTime.Now - experimentStartTime; string timeString = $"{elapsed.Minutes:00}:{elapsed.Seconds:00}.{elapsed.Milliseconds:000}"; // 添加新行到DataGridView int rowIndex = dgvResults.Rows.Add(); dgvResults.Rows[rowIndex].Cells["Time"].Value = timeString; dgvResults.Rows[rowIndex].Cells["T1"].Value = t1.ToString("0.000"); dgvResults.Rows[rowIndex].Cells["T2"].Value = t2.ToString("0.000"); dgvResults.Rows[rowIndex].Cells["V1"].Value = v1.ToString("0.000"); dgvResults.Rows[rowIndex].Cells["V2"].Value = v2.ToString("0.000"); dgvResults.Rows[rowIndex].Cells["Acc"].Value = acc.ToString("0.000"); // 设置加速度单元格颜色 if (acc > 0) dgvResults.Rows[rowIndex].Cells["Acc"].Style.BackColor = Color.FromArgb(230, 255, 230); else if (acc < 0) dgvResults.Rows[rowIndex].Cells["Acc"].Style.BackColor = Color.FromArgb(255, 230, 230); // 自动滚动到最后一行 if (dgvResults.Rows.Count > 0) dgvResults.FirstDisplayedScrollingRowIndex = dgvResults.Rows.Count - 1; // 更新图表 UpdatePlot(acc); } catch (Exception ex) { MessageBox.Show($"数据处理错误: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } // 解析双精度值,使用不变文化 private double ParseDouble(string value) { return double.Parse(value.Trim(), CultureInfo.InvariantCulture); } // 更新图表数据 private void UpdatePlot(double acc) { // 添加新数据点 accelerationData.Add(acc); dataPointCount++; // 限制显示点数 if (accelerationData.Count > 100) accelerationData.RemoveAt(0); // 清除原有数据 chartPlot.Series["加速度"].Points.Clear(); // 添加新数据点 for (int i = 0; i < accelerationData.Count; i++) { chartPlot.Series["加速度"].Points.AddXY(i + 1, accelerationData[i]); } // 更新标题 chartPlot.Titles[0].Text = $"加速度变化曲线 (共 {dataPointCount} 个数据点)"; // 自动调整Y轴范围 if (accelerationData.Count > 0) { double min = accelerationData[0]; double max = accelerationData[0]; foreach (double val in accelerationData) { if (val < min) min = val; if (val > max) max = val; } // 添加边距 double range = max - min; if (range < 0.1) range = 0.1; // 避免过小范围 min = min - range * 0.1; max = max + range * 0.1; // 更新Y轴范围 chartPlot.ChartAreas["MainArea"].AxisY.Minimum = min; chartPlot.ChartAreas["MainArea"].AxisY.Maximum = max; } // 更新X轴范围 chartPlot.ChartAreas["MainArea"].AxisX.Minimum = 1; chartPlot.ChartAreas["MainArea"].AxisX.Maximum = accelerationData.Count > 0 ? accelerationData.Count + 1 : 10; // 刷新图表 chartPlot.Invalidate(); } // 导出数据到Excel(使用EPPlus库) private void btnExport_Click(object sender, EventArgs e) { if (dgvResults.Rows.Count <= 1) // 检查是否有数据 { MessageBox.Show("没有数据可导出!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } using (SaveFileDialog sfd = new SaveFileDialog()) { sfd.Filter = "Excel 文件|*.xlsx"; sfd.Title = "保存实验数据"; sfd.FileName = $"气垫导轨实验_{DateTime.Now:yyyyMMdd_HHmmss}.xlsx"; if (sfd.ShowDialog() == DialogResult.OK) { try { ExcelExporter.ExportToExcel(dgvResults, accelerationData, sfd.FileName); MessageBox.Show("数据导出成功! Excel文件已生成。", "导出完成", MessageBoxButtons.OK, MessageBoxIcon.Information); // 尝试打开导出的Excel文件 try { System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = sfd.FileName, UseShellExecute = true }); } catch { /* 忽略打开错误 */ } } catch (Exception ex) { MessageBox.Show($"导出失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } } // 计算平均加速度 private double CalculateAverageAcceleration() { if (accelerationData.Count == 0) return 0; double sum = 0; foreach (double acc in accelerationData) sum += acc; return sum / accelerationData.Count; } // 计算最大加速度 private double CalculateMaxAcceleration() { if (accelerationData.Count == 0) return 0; double max = accelerationData[0]; foreach (double acc in accelerationData) if (Math.Abs(acc) > Math.Abs(max)) max = acc; return max; } // 清除数据 private void btnClear_Click(object sender, EventArgs e) { if (MessageBox.Show("确定要清除所有数据吗? 此操作不可恢复。", "确认清除", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { dgvResults.Rows.Clear(); accelerationData.Clear(); dataPointCount = 0; // 重置实验开始时间 experimentStartTime = DateTime.Now; // 重置图表 InitializePlot(); } } } // Excel导出助手类 public static class ExcelExporter { public static void ExportToExcel(DataGridView dgv, List<double> accelerationData, string filePath) { // 创建Excel包 using (ExcelPackage excelPackage = new ExcelPackage()) { // 1. 创建实验信息表 CreateInfoSheet(excelPackage, dgv, accelerationData); // 2. 创建数据工作表 CreateDataSheet(excelPackage, dgv); // 3. 创建图表工作表(如果有数据) if (accelerationData.Count > 0) { CreateChartSheet(excelPackage, accelerationData); } // 4. 保存文件 FileInfo excelFile = new FileInfo(filePath); excelPackage.SaveAs(excelFile); } } private static void CreateInfoSheet(ExcelPackage excelPackage, DataGridView dgv, List<double> accelerationData) { ExcelWorksheet infoSheet = excelPackage.Workbook.Worksheets.Add("实验信息"); // 标题行 infoSheet.Cells[1, 1].Value = "气垫导轨实验报告"; infoSheet.Cells[1, 1, 1, 6].Merge = true; infoSheet.Cells[1, 1].Style.Font.Bold = true; infoSheet.Cells[1, 1].Style.Font.Size = 16; infoSheet.Cells[1, 1].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; // 实验信息 infoSheet.Cells[3, 1].Value = "实验时间"; infoSheet.Cells[3, 2].Value = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); infoSheet.Cells[4, 1].Value = "数据点数"; infoSheet.Cells[4, 2].Value = dgv.Rows.Count - 1; infoSheet.Cells[5, 1].Value = "平均加速度"; double avgAcc = CalculateAverageAcceleration(accelerationData); infoSheet.Cells[5, 2].Value = avgAcc.ToString("0.000") + " m/s²"; infoSheet.Cells[6, 1].Value = "最大加速度"; double maxAcc = CalculateMaxAcceleration(accelerationData); infoSheet.Cells[6, 2].Value = maxAcc.ToString("0.000") + " m/s²"; // 设置列宽 infoSheet.Column(1).Width = 15; infoSheet.Column(2).Width = 25; } private static void CreateDataSheet(ExcelPackage excelPackage, DataGridView dgv) { ExcelWorksheet dataSheet = excelPackage.Workbook.Worksheets.Add("实验数据"); // 添加标题行 for (int i = 0; i < dgv.Columns.Count; i++) { dataSheet.Cells[1, i + 1].Value = dgv.Columns[i].HeaderText; dataSheet.Cells[1, i + 1].Style.Fill.PatternType = ExcelFillStyle.Solid; dataSheet.Cells[1, i + 1].Style.Fill.BackgroundColor.SetColor(Color.LightBlue); dataSheet.Cells[1, i + 1].Style.Font.Bold = true; dataSheet.Cells[1, i + 1].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; } // 添加数据行 for (int row = 0; row < dgv.Rows.Count - 1; row++) { for (int col = 0; col < dgv.Columns.Count; col++) { var cellValue = dgv.Rows[row].Cells[col].Value; ExcelRange cell = dataSheet.Cells[row + 2, col + 1]; if (col == 0) // 时间列 { cell.Value = cellValue?.ToString(); } else if (double.TryParse(cellValue?.ToString(), out double numValue)) { cell.Value = numValue; cell.Style.Numberformat.Format = "0.000"; // 加速度列特殊样式 if (col == 5) { cell.Style.Font.Color.SetColor( numValue > 0 ? Color.DarkGreen : Color.DarkRed); } } else { cell.Value = cellValue?.ToString(); } } } // 自动调整列宽 dataSheet.Cells.AutoFitColumns(); // 添加表格边框 using (ExcelRange range = dataSheet.Cells[1, 1, dgv.Rows.Count, dgv.Columns.Count]) { range.Style.Border.Top.Style = ExcelBorderStyle.Thin; range.Style.Border.Bottom.Style = ExcelBorderStyle.Thin; range.Style.Border.Left.Style = ExcelBorderStyle.Thin; range.Style.Border.Right.Style = ExcelBorderStyle.Thin; } } private static void CreateChartSheet(ExcelPackage excelPackage, List<double> accelerationData) { ExcelWorksheet chartSheet = excelPackage.Workbook.Worksheets.Add("加速度曲线"); // 添加标题行 chartSheet.Cells[1, 1].Value = "实验序号"; chartSheet.Cells[1, 2].Value = "加速度 (m/s²)"; // 添加数据 for (int i = 0; i < accelerationData.Count; i++) { chartSheet.Cells[i + 2, 1].Value = i + 1; chartSheet.Cells[i + 2, 2].Value = accelerationData[i]; } // 创建折线图 ExcelLineChart chart = chartSheet.Drawings.AddChart("加速度曲线", eChartType.Line) as ExcelLineChart; chart.Title.Text = "加速度变化曲线"; chart.SetPosition(1, 0, 3, 0); chart.SetSize(800, 400); // 添加数据系列 var series = chart.Series.Add( chartSheet.Cells[2, 2, accelerationData.Count + 1, 2], chartSheet.Cells[2, 1, accelerationData.Count + 1, 1]); series.Header = "加速度"; // 设置图表样式 chart.YAxis.Title.Text = "加速度 (m/s²)"; chart.XAxis.Title.Text = "实验序号"; // 添加趋势线 var trendline = series.TrendLines.Add(eTrendLine.Linear); trendline.DisplayEquation = true; trendline.DisplayRSquaredValue = false; // 设置图表区域样式 chart.Legend.Position = eLegendPosition.Bottom; chart.Legend.Font.Size = 10; chart.Title.Font.Size = 14; chart.Title.Font.Bold = true; } private static double CalculateAverageAcceleration(List<double> accelerationData) { if (accelerationData.Count == 0) return 0; double sum = 0; foreach (double acc in accelerationData) sum += acc; return sum / accelerationData.Count; } private static double CalculateMaxAcceleration(List<double> accelerationData) { if (accelerationData.Count == 0) return 0; double max = accelerationData[0]; foreach (double acc in accelerationData) if (Math.Abs(acc) > Math.Abs(max)) max = acc; return max; } } // 程序入口类 static class Program { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() { // 设置EPPlus许可证(非商业用途) ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial; Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); } }
}
请你在这个代码的基础上修改我上个一发出的错误