第一次真正意义上做小项目,根据对方所提需求,慢慢的学习并实践。
在之前我们是通过ExcelDataReader插件将Excel的内容导入datagridview控件,那今天是将导入的数据从datagridview中导出为Excel。
在导出时需要进行一些特殊的处理。
(一)界面设计
我的界面不是那么美观,哈哈哈,我也想好看,搞不出来,呜呜。
(二)代码块
导入的过程上一篇内容有了,这块主要是导出过程的代码啦。
(1)导出数据部分
private void ExportToExcel(DataGridView dataGridView1)
{
if (txtFileName.Text.Equals(""))
{
MessageBox.Show("未打开文件,请打开文件!");
return;
}
if (dataGridView1.Rows.Count == 0)
{
MessageBox.Show("请选择表格");
return;
}
if (addColumns.Text == "" || joinColumns.Text == "" || duplicateColumn.Text == "")
{
MessageBox.Show("请输入要操作的列!");
return;
}
//声明一个字符串来接收文本的路径
string fileName = "";
string saveFileName = "";
SaveFileDialog saveDialog = new SaveFileDialog();
//扩展名
saveDialog.DefaultExt = "xlsx";
saveDialog.Filter = "Excel文件| *.xlsx;*.xls";
//打开文件夹保存位置
saveDialog.ShowDialog();
saveFileName = saveDialog.FileName;
if (saveFileName.IndexOf(":") < 0) return; //被点了取消
//创建Excel
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
//判断创建Excel有没有成功
if (xlApp == null)
{
MessageBox.Show("无法创建Excel对象,您可能未安装Excel");
return;
}
//工作簿对象
Microsoft.Office.Interop.Excel.Workbooks workbooks = xlApp.Workbooks;
//System.Reflection.Missing miss = System.Reflection.Missing.Value;
//创建工作簿(Workbook:即Excel文件主体本身)
Microsoft.Office.Interop.Excel.Workbook workbook = workbooks.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet);
//创建工作表(即Excel里的子表sheet)1表示在子表sheet1里进行数据导出
Microsoft.Office.Interop.Excel.Worksheet worksheet = (Microsoft.Office.Interop.Excel.Worksheet)workbook.Worksheets[1]; //取得sheet1
//将数据导入到工作表的单元格
//写入标题行
for (int a = 0; a < dataGridView1.Columns.Count; a++)
{
if (this.dgvData.Columns[a].Visible == true)
{
//列标题单元格的标题文本 //excel单元格第一个从索引1开始,第一行第a+1列,因为a从0开始取
worksheet.Cells[1, a + 1] = dataGridView1.Columns[a].HeaderText;
}
}
///把DataGridView当前页的数据保存在Excel中 ///
//求和列值
int addColumn = 1;
addColumn = Convert.ToInt32(addColumns.Text);
//addColumn = addColumn + 1;
//拼接列
int joinColumn = 1;
joinColumn = Convert.ToInt32(joinColumns.Text);
//joinColumn = joinColumn + 1;
//重复列
int duplicateIs = 1;
duplicateIs = Convert.ToInt32(duplicateColumn.Text);
bool isDuplicate;
int i = 0;
while (i < dataGridView1.Rows.Count)
{
isDuplicate = false;//是否重复
List<int> list = new List<int>();
//行之间比较
for (int nbRowCompare = i; nbRowCompare < dataGridView1.Rows.Count; nbRowCompare++)
{
if (dataGridView1[duplicateIs - 1, nbRowCompare].Value != null)
{
//判断是否重复
if (dataGridView1[duplicateIs - 1, nbRowCompare].Value.ToString().Equals(dataGridView1[duplicateIs - 1, i].Value.ToString()))
{
//重复的放在这里面 (把对象放入集合)
list.Add(nbRowCompare);
isDuplicate = true;
}
}
}
//Console.WriteLine(list);
//如果重复,将第二列的内容拼接 拼接第几列
if (isDuplicate)
{
for (int a = 1; a < list.Count; a++)
{
//拼接 如果为空则无,不为空则连接
if (dataGridView1[joinColumn - 1, list[a]].Value == null || (dataGridView1[joinColumn - 1, list[a]].Value.ToString()).Equals(""))
{
}
else
{
拼接
dataGridView1[joinColumn - 1, list[0]].Value += "," + (string)(dataGridView1[joinColumn - 1, list[a]].Value);
//求和列
dataGridView1[addColumn - 1, list[0]].Value = Convert.ToInt32(dataGridView1[addColumn - 1, list[0]].Value.ToString()) + Convert.ToInt32(dataGridView1[addColumn - 1, list[a]].Value.ToString());
}
}
//删除重复行
for (int a = list.Count - 1; a > 0; a--)
{
dataGridView1.Rows.RemoveAt(list[a]);
}
}
for (int j = 0; j < dataGridView1.Columns.Count; j++)
{
if (dataGridView1[j, i].Value != null)
{
//Fun函数调用
dataGridView1[joinColumn - 1, i].Value = Fun(dataGridView1[joinColumn - 1, i].Value.ToString());
worksheet.Cells[i + 2, j + 1] = dataGridView1[j, i].Value.ToString();
}
}
i++;
ProgressBar1.Maximum = dataGridView1.Rows.Count;
ProgressBar1.Value = i;
Application.DoEvents();
}
//该对象代表整个范围列(或列),其中包含指定的范围。 //列宽自适应
//worksheet.Columns.EntireColumn.AutoFit();
//提示框
MessageBox.Show(fileName + "保存成功");
if (saveFileName != "")
{
try
{
workbook.Saved = true;
//保存工作簿的副本文件但不修改打开工作簿在内存中。
workbook.SaveCopyAs(saveFileName);
}
catch (Exception ex)
{
MessageBox.Show("导出文件可能正在被打断!" + ex.Message);
}
}
//释放可能还没有释放的进程
xlApp.Quit();
GC.Collect();
}
(2)拆分字符函数
public string Fun(string input)
{
List<string> resultStr = new List<string>();
//例如: C164 - C166,C360 - C362
string[] vs1 = input.Split(','); //C164-C166 C360-C362
foreach (string s in vs1)
{
if (s.Contains('-'))
{
//C164 - C166
string[] vs2 = s.Split('-');
//C164 C166
string start = Regex.Replace(vs2[0], "[a-z]", "", RegexOptions.IgnoreCase);//C164
string end = Regex.Replace(vs2[1], "[a-z]", "", RegexOptions.IgnoreCase);//C166
string code = vs2[0].Replace(start, "");//C = ""
int start1 = Convert.ToInt32(start);//164
int end1 = Convert.ToInt32(end);//166
for (int a = start1; a <= end1; a++)
{
//164
string rs = code + a;//C164
resultStr.Add(rs);
}
}
else
{
resultStr.Add(s);
}
}
//resultStr C164 C165 C166 C360 C361 C362
return string.Join(",", resultStr);
}
(3)结果展示
我这个板块具体得功能是选择相应料号列、点位列、点位数量列后,完成将料号列重复行删除,在删除前,将它的点位列拼接上,同时计算点位用量列的和。
(4)例子
导出前:
导出后:
在某些内容我可能解释的不是很清楚,大家可以看代码里的注释。有什么问题,可私或评论区见。希望对有需要的伙伴有所帮助。