目录
3 将显示在DataGirdView中的数据导出到Excel表格文件
4. 重写OnLayout方法,让窗口中的控件大小随窗口大小自适应。
因为最近要用到winform制作插件,学习了c#和winform控件基础功能,以一个小项目进行练习,在此记录一下。
本项目实现如下功能:
1. 通过浏览文件的形式读取.dat文本数据;
2. 使用dataGridView控件显示数据;
3. 点击导出Excel按钮输出Excel文件;
4. 控件大小随窗口大小的改变自适应。
制作的窗口如下图。

选c#;Windows;桌面;Windows窗体应用;(没有的话需要先安装一下)


在工具箱里拖进去一个TextBox控件和PictureBox控件。调整大小和位置如下图。

这里也可用Button控件代替PictureBox控件,用到的都是Click事件,效果是一样的。

在属性里面修改text文本框的(Name)属性。改名字是为了程序里面调用的时候好区分。
修改ImageBox控件的(Name)和Image属性。Image属性用来更改图标样式(这里的图标来源于iconfont-阿里巴巴矢量图标库,搜索“打开”关键字即可下载,文件名最好别用汉字)
给ImageBox控件添加一个Click事件。在自动生成的Click事件中添加点击事件处理程序。

代码如下:

private void Search_btn_Click(object sender, EventArgs e) {
//浏览文件
OpenFileDialog openFileDialog2 = new OpenFileDialog();
openFileDialog2.Multiselect = false; //该值确定是否可以选择多个文件
openFileDialog2.Title = "请选择文件";
openFileDialog2.Filter = "文档(*.dat;*.txt)|*.dat;*.txt";
if (openFileDialog2.ShowDialog() == DialogResult.OK) {
if (openFileDialog2.FileName != "") {
this.Search_text.Text = openFileDialog2.FileName;
}
}
}
控件使用效果如下:选择文件后左侧自动出现文件路径和名称

为什么要自定义一个控件?其实可以直接在form1中直接添加TextBox控件和ImageBox控件实现同样的功能,只是这样封装成一个控件觉得可以练习一下制作自定义控件,也方便以后直接拿来用。

给DataGridView控件添加列。因为这需要显示的表格数据列名是固定的,所以可以直接编辑添加。点击添加的DataGridView控件,点击右上角会出现的小三角 , 点击编辑列。


从工具箱中拖入一个Button控件。在属性栏中修改(Name)属性和Text属性,Text属性用于更改按钮上显示的文字。

在事件栏中添加一个Click事件。跟之前一样,鼠标点一下Click事件右侧按回车键即可自动生成点击事件。

在Click事件中添加如下代码。程序思路:先按条件筛取.dat文件中有用的一行数据存入input中,然后分别截取有用的数据段赋值给对应的每一列。
/// <summary>
/// 获取两个字符串中间的字符串
/// </summary>
/// <param name="str">要处理的字符串,例ABCD</param>
/// <param name="str1">第1个字符串,例AB</param>
/// <param name="str2">第2个字符串,例D</param>
/// <returns>例返回C</returns>
private string GetBetweenStr(string str, string str1, string str2) {
int i1 = str.IndexOf(str1);
if (i1 < 0) //找不到返回空
{
return "";
}
int i2 = str.IndexOf(str2, i1 + str1.Length); //从找到的第1个字符串后再去找
if (i2 < 0) //找不到返回空
{
return "";
}
return str.Substring(i1 + str1.Length, i2 - i1 - str1.Length);
}
//确定按钮点击事件
private void button_Confirm_Click(object sender, EventArgs e) {
//点击确认按钮事件,读取.dat文件数据并显示出来,弹出对话框“数据已显示”
//先确认是否选择了正确文件
string filePath = SearchBox1.Search_text.Text;//文件地址
string fileExt = Path.GetExtension(filePath).ToLower();//获取文件的拓展名
string fileNameData = Path.GetFileName(filePath);
if (!File.Exists(filePath)) {
MessageBox.Show("文件不存在");
return;
}
if (!(fileExt == ".dat")) {
MessageBox.Show("请选择.dat格式文件");
return;
}
using (StreamReader sr = File.OpenText(filePath)) {
string input; //存放.dat文件的单行数据
while ((input = sr.ReadLine()) != null) { //循环取出.dat文件的每行数据
//判断前十位是否为DECL E6POS
if (input.Contains("DECL E6POS")) {
Console.WriteLine(input);
string name = GetBetweenStr(input, "E6POS ", "=");
string X = GetBetweenStr(input, "X ", ",");
string Y = GetBetweenStr(input, "Y ", ",");
string Z = GetBetweenStr(input, "Z ", ",");
string A = GetBetweenStr(input, "A ", ",");
string B = GetBetweenStr(input, "B ", ",");
string C = GetBetweenStr(input, "C ", ",");
//创建一个object[7]存表格中的一行数据,一共7列
object[] row = new object[7];
row[0] = name; row[1] = X; row[2] = Y;
row[3] = Z; row[4] = A; row[5] = B; row[6] = C;
//在dataGridView1中新建一行并将存在row中的数据写入
dataGridView1.Rows.Add(row);
}
}
sr.Close();
}
添加Button控件。修改(Name)属性和Text属性。

添加Click事件。

在自动生成的Click事件是添加下面代码。
private void saveButton_Click(object sender, EventArgs e) {
//保存按钮,弹出对话框选择保存路径和文件名
//验证是否有文件
//弹出对话框浏览保存路径和文件名称
string filePath = SearchBox1.Search_text.Text; //.dat文件地址
string fileNameData = Path.GetFileNameWithoutExtension(filePath); //.dat文件名
string fileName = fileNameData; //可以在这里设置默认文件名
string saveFileName = ""; //文件保存名
SaveFileDialog saveDialog = new SaveFileDialog(); //实例化文件对象
saveDialog.DefaultExt = "xlsx";//文件默认扩展名
saveDialog.Filter = "Excel文件|*.xlsx";//获取或设置当前文件名筛选器字符串,该字符串决定对话框的“另存为文件类型”或“文件类型”框中出现的选择内容。
saveDialog.FileName = fileName;
saveDialog.ShowDialog();//打开保存窗口给你选择路径和设置文件名
saveFileName = saveDialog.FileName;
if (saveFileName.IndexOf(":") < 0) return; //被点了取消
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
if (xlApp == null) {
MessageBox.Show("无法创建Excel对象,您的电脑可能未安装Excel");
return;
}
Microsoft.Office.Interop.Excel.Workbooks workbooks = xlApp.Workbooks;//Workbooks代表一个 Microsoft Excel 工作簿
Microsoft.Office.Interop.Excel.Workbook workbook = workbooks.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet);//新建一个工作表。 新工作表将成为活动工作表。
Microsoft.Office.Interop.Excel.Worksheet worksheet = (Microsoft.Office.Interop.Excel.Worksheet)workbook.Worksheets[1];//取得sheet1
//写入标题
for (int i = 0; i < dataGridView1.ColumnCount; i++)//遍历循环获取DataGridView标题
{ worksheet.Cells[1, i + 1] = dataGridView1.Columns[i].HeaderText; }// worksheet.Cells[1, i + 1]表示工作簿第一行第i+1列,Columns[i].HeaderText表示第i列的表头
//写入数值
for (int r = 0; r < dataGridView1.Rows.Count; r++)//这里表示数据的行标,dataGridView1.Rows.Count表示行数
{
for (int i = 0; i < dataGridView1.ColumnCount; i++)//遍历r行的列数
{
worksheet.Cells[r + 2, i + 1] = dataGridView1.Rows[r].Cells[i].Value;//Cells[r + 2, i + 1]表示工作簿从第二行开始第一行保存为表头了,dataGridView1.Rows[r].Cells[i].Value获取列的r行i值
}
System.Windows.Forms.Application.DoEvents();//实时更新表格
}
worksheet.Columns.EntireColumn.AutoFit();//列宽自适应
MessageBox.Show(fileName + "资料保存成功", "提示", MessageBoxButtons.OK);//提示保存成功
if (saveFileName != "")//saveFileName保存文件名不为空
{
try {
workbook.Saved = true;//获取或设置一个值,该值指示工作簿自上次保存以来是否进行了更改
workbook.SaveCopyAs(saveFileName); //fileSaved = true;将工作簿副本保存到文件中,但不修改内存中打开的工作簿
}
catch (Exception ex) {//fileSaved = false;
MessageBox.Show("导出文件时出错,文件可能正被打开!\n" + ex.Message);
}
}
xlApp.Quit();
GC.Collect();//强行销毁
}
效果如下:


实现代码如下:
protected override void OnLayout(LayoutEventArgs levent) {
//1 调用父类的OnLayout(),不是必需的
base.OnLayout(levent);
//2 获取窗口大小 ClientSize (仅客户区,不含标题栏)
int w = this.ClientSize.Width;
int h = this.ClientSize.Height;
//3 计算每一个控件的位置和大小
int yoff = 0;//此变量用于设置间隔
yoff = 30;//第一行控件距顶部的间隔
this.SearchBox1.Location = new Point(30, yoff);
this.SearchBox1.Size = new Size(w - 145, 30);
this.button_Confirm.Location = new Point(w - 110, yoff);
this.button_Confirm.Size = new Size(80, 30);
yoff += 30;//the height of the first row
yoff += 5;//与上一行控件的间隔
this.dataGridView1.Location = new Point(30, yoff);
this.dataGridView1.Size = new Size(w - 60, 300);
yoff += 300;//the height of the second row
yoff += 5;//与上一行控件的间隔
this.saveButton.Location = new Point(w - 160, yoff);
this.saveButton.Size = new Size(130, 30);
}
说明:本文中的许多代码来源于CSDN、B站视频等,部分链接如下,有些是边学边写的可能会遗忘一些原文链接。
C#:获取两个字符串中间的字符串_小鸿1983的博客-CSDN博客
C# DataGridView数据导出Excel文件_IC00的博客-CSDN博客_c# datagridview 导出到excel
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta