C#日常开发随手记------COM组件(Microsoft.Office.Interop.Excel)操作excel、如何创建\删除文件夹

530 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

文章中写了点过程有点啰嗦,想直接看代码的直接下拉看加粗标题处

第一次使用COM组件操作excel,遇到了点坑,也有些感触。 一般来说操作excel,我比较常用的是OleDB,但是OleDB需要安装AccessDatabaseEngine,现在的公司没有特殊情况又不允许随便装东西,所以在出现了“未在本地计算机上注册“microsoft.ACE.oledb.12.0”错误之后无奈放弃,然后又试了Spire,奈何Spire需要收费,在保存excel之后,会出现一个删除不掉的sheet,最后决定使用COM组件进行操作。 先放一个Spire获取excel值的代码(这个可以正常使用,不收费):

Spire读取excel数据代码:

  • 添加引用:

在项目的引用上右击,选择管理NuGet程序包,搜FreeSpire进行安装

  • 代码示例:
/// <summary>
/// 获取并生成Excel
/// </summary>
/// <param name="path"></param>
private void getExcel(string path)
{
    Spire.Xls.Workbook workbook = new Spire.Xls.Workbook();

    workbook.LoadFromFile(path);

    //获取第一张工作表
    Spire.Xls.Worksheet sheet = workbook.Worksheets[0];
    //保存为csv格式
    sheet.SaveToFile("Customer.csv", ",", Encoding.UTF8);

    List<string[]> list = new List<string[]>();
    StreamReader fileReader = new StreamReader("Customer.csv");
    string strLine = "";
    while (strLine != null)
    {
        strLine = fileReader.ReadLine();
        if (strLine != null && strLine.Length > 0)
        {
            list.Add(strLine.Split(','));
        }
    }
    fileReader.Close();

    list.Remove(list[0]);
	
	//item便是为行
    foreach (var item in list)
    {
    	//取出来的值(item[0])前后会有"\",试了别的方法没啥用,只能用最笨的截取字符串的方法
        string value1 = cutOut(item[0]);
        string value2 = cutOut(item[1]);
    }
    this.Close();
}

/// <summary>
/// 截取字符串
/// </summary>
/// <param name="value">需要截取的字符串</param>
/// <returns></returns>
public string cutOut(string value)
{
    string subValue = "";
    subValue = value.Substring(0, value.Length - 1);
    subValue = subValue.Substring(1, subValue.Length - 1);
    return subValue;
}

如果有可以优化的地方,看到的大佬可以评论区指点一下共同进步,谢谢!

言归正传,回到COM组件,需求经历过一次变更,而卡住的地方在第二次修改的时候。

  • 第一次,从一个配置excel(PTIT.xlsx)中获取需要写入的值,然后把这值填入模板excel,最后保存为xlsx格式的excel。 操作如下:

保存为xlsx格式的代码示例:

  • 添加引用: 在项目的引用上右击,选择管理NuGet程序包,搜FreeSpire进行安装
  • 增加命名空间引用: using Excel = Microsoft.Office.Interop.Excel;
  • 获取excel数据代码:
/// <summary>
/// 获取Excel
/// </summary>
/// <param name="path"></param>
private void GetExcel(string path)
{
    Excel.Workbooks workbooks = app.Workbooks;
    Excel._Workbook workbook = workbooks.Add(AppDomain.CurrentDomain.BaseDirectory + @"\PTIT.xlsx"); //加载模板
    Excel.Sheets sheets = workbook.Sheets;
    Excel._Worksheet worksheet = (Excel._Worksheet)sheets.get_Item(1); //第一个工作薄。

    for (int i = 1; i <= worksheet.UsedRange.Rows.Count; i++)
    {
        if (i != 1)
        {
            //获取第一个sheet中的值
            string value1 = worksheet.Cells[i, 1].Value;
            string value2 = worksheet.Cells[i, 2].Value;

        }
    }
}
  • 操作并保存excel:
/// <summary>
/// 填写excel并保存
/// </summary>
/// <param name="value1">第一个值</param>
/// <param name="value2">第二个值</param>
private void Export(string value1, string value2)
{
    Excel.Workbooks workbooks = app.Workbooks;
    //Directory.GetCurrentDirectory() 用于获取当前项目所在的路径一般为...\bin\Debug
    Excel._Workbook workbook = workbook = workbooks.Add(Directory.GetCurrentDirectory() + @"\需要修改的excel.xlsx"); //加载模板
    Excel.Sheets sheets = workbook.Sheets;
    Excel._Worksheet worksheet = (Excel._Worksheet)sheets.get_Item(1); //第一个工作薄。
    if (worksheet == null)
        return;

    //下标从1开始
    //给第五行,第三列赋值
    worksheet.Cells[5, 3] = value1;
    //给第六行,第四列赋值
    worksheet.Cells[6, 4] = value2;
    //不需要弹出消息框
    app.AlertBeforeOverwriting = false;
    //保存到D盘下
    string savaPath =   @"D:\修改完的excel.xlsx";
    workbook.SaveAs(savaPath, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value);
    workbook.Close(SaveChanges: true);
}

第二次需求变为保存为.xlsm格式.然后就发现上面的方法没有办法直接用,用上面的SaveAs保存报错。报错信息为:

[这个扩展名不能用于所选择的文件格式。请在[文件名]框中更改文件扩展名,或在[文件种类]框中选择其他文件格式]

COM组件里保存方法有: 1)workbook.Save() 2)workbook.SaveAs() 3)workbook.SaveCopyAs()

workbook.Save()无法指定路径,所以首先排除。

workbook.SaveAs()按道理来说应该可以保存xlsm,所以在查了资料后更改了其中的参数: workbook.SaveAs(savaPath, XlFileFormat.xlXMLSpreadsheet, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, XlSaveConflictResolution.xlLocalSessionChanges, Missing.Value, Missing.Value, Missing.Value, Missing.Value);

保存成功,但是保存下来的excel双击打开提示:

[文件不能打开,格式或者扩展名格式不正确]

点击消息框的OK之后,整个excel变成空白并且损坏。(如果有大神看到知道原因,希望可以指点一下)

各种查询无果后,尝试了最后一个保存方法 workbook.SaveCopyAs(): 结果是成功保存下来,而且excel可以用,但是很尴尬的是,每次都会弹出来一个另存为选择路径的窗口,那么问题就还是没有解决。最终死马当活马医,更改了代码:

Excel._Workbook workbook = workbooks.Add(AppDomain.CurrentDomain.BaseDirectory + @"\PTIT.xlsx"); //加载模板

改为

Excel._Workbook workbook = workbooks.Open(AppDomain.CurrentDomain.BaseDirectory + @"\PTIT.xlsx"); //加载模板

才最终成功。

保存为.xlsm格式excel的代码示例:

  • 添加引用: 在项目的引用上右击,选择管理NuGet程序包,搜FreeSpire进行安装
  • 增加命名空间引用: using Excel = Microsoft.Office.Interop.Excel;
  • 获取Excel数据(与上面的获取代码一致)
/// <summary>
/// 获取Excel
/// </summary>
/// <param name="path"></param>
private void GetExcel(string path)
{
    Excel.Workbooks workbooks = app.Workbooks;
    Excel._Workbook workbook = workbooks.Add(AppDomain.CurrentDomain.BaseDirectory + @"\PTIT.xlsx"); //加载模板
    Excel.Sheets sheets = workbook.Sheets;
    Excel._Worksheet worksheet = (Excel._Worksheet)sheets.get_Item(1); //第一个工作薄。

    for (int i = 1; i <= worksheet.UsedRange.Rows.Count; i++)
    {
        if (i != 1)
        {
            //获取第一个sheet中的值
            string value1 = worksheet.Cells[i, 1].Value;
            string value2 = worksheet.Cells[i, 2].Value;

        }
    }
}
  • 操作并保存excel:
/// <summary>
/// 填写excel并保存
/// </summary>
/// <param name="value1">第一个值</param>
/// <param name="value2">第二个值</param>
private void Export(string value1, string value2)
{
    Excel.Workbooks workbooks = app.Workbooks;
    //Directory.GetCurrentDirectory() 用于获取当前项目所在的路径一般为...\bin\Debug
    Excel._Workbook workbook = workbook = workbooks.Open(Directory.GetCurrentDirectory() + @"\需要修改的excel.xlsm"); //加载模板
    Excel.Sheets sheets = workbook.Sheets;
    Excel._Worksheet worksheet = (Excel._Worksheet)sheets.get_Item(1); //第一个工作薄。
    if (worksheet == null)
        return;

    //下标从1开始
    //给第五行,第三列赋值
    worksheet.Cells[5, 3] = value1;
    //给第六行,第四列赋值
    worksheet.Cells[6, 4] = value2;
    //不需要弹出消息框
    app.AlertBeforeOverwriting = false;
    //保存到D盘下
    string savaPath = @"D:\修改完的excel.xlsm";
    workbook.SaveCopyAs(savaPath);
    workbook.Close(SaveChanges: true);
}

创建\删除文件夹,附代码:

//判断D盘下是否存在other文件夹
if (!Directory.Exists(@"D:\other"))
{
    //如果不存在就创建
    Directory.CreateDirectory(@"D:\other");
}
//删除D盘下的other文件夹
Directory.Delete(@"D:\other", true);

excel中各个方法的作用参考文献: C#操作Excel方法总结

本文中的一些问题,以及如果有什么错误或者可以优化的地方,欢迎看到的大神评论留言指出,谢谢。