Compare commits

..

2 Commits

Author SHA1 Message Date
Developer
ee620a3255 转换为通用WinForms应用模板
## 主要功能
- 清理Excel合并业务逻辑,保留基础框架
- 单exe打包配置(ILRepack示例)
- 应用图标和UI按钮图标配置
- .NET Framework 4.8环境检测
- 通用UI界面(文件夹选择、日志显示等)

## 模板用途
可直接作为新WinForms项目的基础模板
- 只需添加具体业务逻辑即可
- 支持Win7兼容性
- 完整的打包和图标配置示例

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 14:45:46 +08:00
Developer
954e564318 添加程序图标和UI图标功能
1. 程序窗体显示app.ico图标
2. 两个浏览按钮使用app.ico图标显示
3. 添加错误处理,图标加载失败时回退到文字显示
4. 优化编译输出,减少终端窗口显示

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 14:43:07 +08:00
4 changed files with 51 additions and 207 deletions

View File

@ -2,7 +2,7 @@
using System.Windows.Forms;
using System.Drawing;
namespace WinFormsApp1
namespace WinFormsAppTemplate
{
partial class Form1
{
@ -37,7 +37,7 @@ namespace WinFormsApp1
// 主窗体设置
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(600, 400);
Text = "Excel合并工具";
Text = "WinForms应用模板";
StartPosition = FormStartPosition.CenterScreen;
// 创建控件
@ -61,7 +61,7 @@ namespace WinFormsApp1
txtLog = new TextBox();
// 设置源文件夹组
grpSourceFolder.Text = "文件夹";
grpSourceFolder.Text = "输入文件夹";
grpSourceFolder.Location = new Point(10, 10);
grpSourceFolder.Size = new Size(580, 60);
grpSourceFolder.TabStop = false;
@ -73,10 +73,21 @@ namespace WinFormsApp1
txtSourcePath.Location = new Point(45, 22);
txtSourcePath.Size = new Size(470, 23);
btnBrowseSource.Text = "浏览";
btnBrowseSource.Text = "";
btnBrowseSource.Location = new Point(520, 20);
btnBrowseSource.Size = new Size(50, 25);
btnBrowseSource.Click += new EventHandler(btnBrowseSource_Click);
// 设置浏览按钮图标
try
{
btnBrowseSource.Image = Image.FromFile("app.ico");
btnBrowseSource.ImageAlign = ContentAlignment.MiddleCenter;
}
catch
{
// 如果图标加载失败,显示文字
btnBrowseSource.Text = "浏览";
}
grpSourceFolder.Controls.Add(lblSourcePath);
grpSourceFolder.Controls.Add(txtSourcePath);
@ -95,10 +106,21 @@ namespace WinFormsApp1
txtOutputPath.Location = new Point(45, 22);
txtOutputPath.Size = new Size(470, 23);
btnBrowseOutput.Text = "浏览";
btnBrowseOutput.Text = "";
btnBrowseOutput.Location = new Point(520, 20);
btnBrowseOutput.Size = new Size(50, 25);
btnBrowseOutput.Click += new EventHandler(btnBrowseOutput_Click);
// 设置浏览按钮图标
try
{
btnBrowseOutput.Image = Image.FromFile("app.ico");
btnBrowseOutput.ImageAlign = ContentAlignment.MiddleCenter;
}
catch
{
// 如果图标加载失败,显示文字
btnBrowseOutput.Text = "浏览";
}
grpOutputFolder.Controls.Add(lblOutputPath);
grpOutputFolder.Controls.Add(txtOutputPath);
@ -108,7 +130,7 @@ namespace WinFormsApp1
pnlButtons.Location = new Point(10, 150);
pnlButtons.Size = new Size(580, 40);
btnMerge.Text = "合并";
btnMerge.Text = "执行";
btnMerge.Location = new Point(10, 8);
btnMerge.Size = new Size(75, 25);
btnMerge.Click += new EventHandler(btnMerge_Click);

View File

@ -1,29 +1,34 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using System.Data;
namespace WinFormsApp1
namespace WinFormsAppTemplate
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// 设置窗体图标
try
{
this.Icon = new Icon("app.ico");
}
catch
{
// 如果图标文件不存在或格式错误,忽略
}
}
private void btnBrowseSource_Click(object sender, EventArgs e)
{
using (FolderBrowserDialog dialog = new FolderBrowserDialog())
{
dialog.Description = "选择Excel文件夹";
dialog.Description = "选择文件夹";
if (dialog.ShowDialog() == DialogResult.OK)
{
txtSourcePath.Text = dialog.SelectedPath;
txtOutputPath.Text = dialog.SelectedPath; // 默认输出到源文件夹
Log($"源文件夹: {dialog.SelectedPath}");
Log($"选择的文件夹: {dialog.SelectedPath}");
}
}
}
@ -56,192 +61,8 @@ namespace WinFormsApp1
private void btnMerge_Click(object sender, EventArgs e)
{
// 前置校验
if (string.IsNullOrEmpty(txtSourcePath.Text) || string.IsNullOrEmpty(txtOutputPath.Text))
{
MessageBox.Show("请选择源文件夹和输出文件夹", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
try
{
MergeExcel();
}
catch (Exception ex)
{
MessageBox.Show($"合并过程中发生错误: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
Log($"合并失败: {ex.Message}");
}
}
private void MergeExcel()
{
var sourceDir = txtSourcePath.Text;
var outputDir = txtOutputPath.Text;
var outputFile = Path.Combine(outputDir, "合并结果.xlsx");
if (!Directory.Exists(sourceDir))
{
MessageBox.Show("源文件夹不存在", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 查找xlsx文件排除合并结果本身
var xlsxFiles = Directory.GetFiles(sourceDir, "*.xlsx")
.Where(f => !Path.GetFileName(f).Equals("合并结果.xlsx", StringComparison.OrdinalIgnoreCase))
.ToArray();
if (xlsxFiles.Length == 0)
{
MessageBox.Show("未找到待合并的Excel文件", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
Log($"找到 {xlsxFiles.Length} 个文件,开始合并...");
progressBar.Maximum = xlsxFiles.Length;
progressBar.Value = 0;
var allData = new List<DataTable>();
var headers = new List<string>();
try
{
// 处理每个文件
for (int idx = 0; idx < xlsxFiles.Length; idx++)
{
var file = xlsxFiles[idx];
var fileName = Path.GetFileName(file);
Log($"处理: {fileName}");
try
{
using (var package = new OfficeOpenXml.ExcelPackage(new FileInfo(file)))
{
if (package.Workbook.Worksheets.Count == 0)
{
Log($"跳过空文件: {fileName}");
continue;
}
var worksheet = package.Workbook.Worksheets[0]; // 使用第一个工作表
var table = new DataTable();
// 获取表头
if (headers.Count == 0)
{
var columnCount = worksheet.Dimension.End.Column;
for (int col = 1; col <= columnCount; col++)
{
var header = worksheet.Cells[1, col].Text?.Trim() ?? $"Column{col}";
headers.Add(header);
table.Columns.Add(header);
}
}
else
{
// 创建相同结构的表
foreach (var header in headers)
{
table.Columns.Add(header);
}
}
// 跳过表头行,从第二行开始读取数据
var rowCount = worksheet.Dimension.End.Row;
for (int row = 2; row <= rowCount; row++)
{
var dataRow = table.NewRow();
var isEmpty = true;
for (int col = 0; col < headers.Count; col++)
{
var cellValue = worksheet.Cells[row, col + 1].Text;
dataRow[col] = cellValue;
if (!string.IsNullOrWhiteSpace(cellValue))
{
isEmpty = false;
}
}
if (!isEmpty)
{
table.Rows.Add(dataRow);
}
}
if (table.Rows.Count > 0)
{
allData.Add(table);
Log($"成功读取 {fileName}: {table.Rows.Count} 行数据");
}
else
{
Log($"跳过无数据文件: {fileName}");
}
}
}
catch (Exception ex)
{
Log($"处理失败: {fileName} - {ex.Message}");
continue;
}
progressBar.Value = idx + 1;
Application.DoEvents();
}
// 合并数据并保存
if (allData.Count == 0)
{
MessageBox.Show("无有效数据可合并", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 创建合并后的Excel文件
using (var outputPackage = new OfficeOpenXml.ExcelPackage())
{
var outputSheet = outputPackage.Workbook.Worksheets.Add("合并结果");
// 写入表头
for (int col = 0; col < headers.Count; col++)
{
outputSheet.Cells[1, col + 1].Value = headers[col];
}
int currentRow = 2;
int totalRows = 0;
// 合并所有数据
foreach (var table in allData)
{
foreach (DataRow row in table.Rows)
{
for (int col = 0; col < headers.Count; col++)
{
outputSheet.Cells[currentRow, col + 1].Value = row[col];
}
currentRow++;
totalRows++;
}
}
// 保存文件
outputPackage.SaveAs(new FileInfo(outputFile));
Log($"合并完成!文件路径: {outputFile}");
Log($"总行数: {totalRows} | 总列数: {headers.Count}");
MessageBox.Show($"合并成功!\n文件{outputFile}\n行数{totalRows}",
"完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
catch (Exception ex)
{
Log($"保存失败: {ex.Message}");
MessageBox.Show($"保存文件失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
MessageBox.Show("这是一个模板项目\n\n功能\n• 单exe打包\n• 应用图标配置\n• UI按钮图标\n• 环境检测\n\n请在此基础上开发你的具体功能", "模板项目", MessageBoxButtons.OK, MessageBoxIcon.Information);
Log("模板功能演示");
}
private void Log(string msg)

View File

@ -2,7 +2,7 @@ using System;
using System.Windows.Forms;
using Microsoft.Win32;
namespace WinFormsApp1
namespace WinFormsAppTemplate
{
internal static class Program
{

View File

@ -4,8 +4,8 @@
<OutputType>WinExe</OutputType>
<TargetFramework>net48</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<AssemblyName>ExcelMerger</AssemblyName>
<RootNamespace>ExcelMerger</RootNamespace>
<AssemblyName>WinFormsAppTemplate</AssemblyName>
<RootNamespace>WinFormsAppTemplate</RootNamespace>
<ApplicationIcon>app.ico</ApplicationIcon>
<!-- 用于单文件发布的配置 -->
<PublishSingleFile>false</PublishSingleFile>
@ -15,21 +15,22 @@
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<!-- 模板项目不需要外部依赖 -->
<!-- 如需合并第三方DLL可在此添加PackageReference -->
<!-- 示例:
<ItemGroup>
<PackageReference Include="EPPlus" Version="4.5.3.3" />
<!-- 用于ILMerge合并依赖项 -->
<PackageReference Include="ILRepack" Version="2.0.18" />
</ItemGroup>
<!-- ILMerge后处理脚本 -->
<Target Name="ILRepack" AfterTargets="Build">
<ItemGroup>
<InputAssemblies Include="$(OutputPath)$(AssemblyName).exe" />
<InputAssemblies Include="$(OutputPath)EPPlus.dll" />
<InputAssemblies Include="$(OutputPath)YourLibrary.dll" />
</ItemGroup>
<Message Text="ILRepack merging..." Importance="high" />
<Exec Command="$(PkgILRepack)\tools\ILRepack.exe /target:exe /out:$(OutputPath)$(AssemblyName)_merged.exe @(InputAssemblies-&gt;'%(FullPath)', ' ')" />
<Message Text="ILRepack merge complete: $(OutputPath)$(AssemblyName)_merged.exe" Importance="high" />
</Target>
-->
</Project>