簡體   English   中英

C# COM Interop Excel:如何使用 Interop Excel 從 C# 寫入單元格?

[英]C# COM Interop Excel: How to write to cells from C# using Interop Excel?

我正在編寫 C# 代碼,最后我想將結果數組導出到 Excel。 為此,我查找了示例代碼以運行第一個模擬結果,然后用於我的代碼。 我嘗試使用 Interop Excel 實現代碼,當代碼運行時,可以打開/創建工作簿、打開/創建工作表、重命名工作表、保存結果我無法更改單元格。 值更改和格式更改都不適合我。 它保存了一個空白的 Excel 文件,其中包含對工作表的更改,可以說。

請參閱下面我嘗試運行的示例代碼:我正在使用 Rider,但嘗試了結果,但在 Visual Studio 中也失敗了。 還嘗試了多台計算機,但沒有成功。 .NET 框架是 4.0.3,安裝的 Interop 包是最新的 15.0.4795(同時還安裝了最新的 15.0.0 版本的 Microsoft Office Core)。 CSV 寫入確實有效(請參閱第一個片段中的注釋部分)。

我不知道還能嘗試什么,如果我能提供進一步的上下文,我很高興。 謝謝您的幫助!

using System.Reflection;
using Excel = Microsoft.Office.Interop.Excel;

public void ExcelExport()
{
    var fileLoc = "...\\test.xlsx";

    // CSV writer
    // using (TextWriter sw = new StreamWriter(fileLoc))
    // {
    //     string strData = "Zaara";
    //     float floatData = 324.563F;//Note it's a float not string
    //     sw.WriteLine("{0},{1}", strData, floatData.ToString("F2"));
    // }
    
    var excelApp = new Excel.Application();
    excelApp.Visible = true;
    excelApp.DisplayAlerts = false;
    var workBook = (Excel.Workbook) excelApp.Workbooks.Add();
    var reportSheet = (Excel.Worksheet) workBook.Worksheets.Add();
    reportSheet.Name = "Report";
    reportSheet.Cells[3, 4] = "Contract Name";
    reportSheet.Range["A2, A2"].Value2 = 10;
    workBook.SaveAs(fileLoc);
    workBook.Close();
    excelApp.DisplayAlerts = true;
    excelApp.Quit();

}


public void ExcelExport2()
{
    var fileLoc = "...\\test2.xlsx";
    
    Excel.Application oXL;
    Excel._Workbook oWB;
    Excel._Worksheet oSheet;
    Excel.Range oRng;

    //Start Excel and get Application object.
    oXL = new Excel.Application();
    oXL.Visible = true;

    //Get a new workbook.
    oWB = (Excel._Workbook)(oXL.Workbooks.Add( Missing.Value ));
    oSheet = (Excel._Worksheet)oWB.ActiveSheet;

    //Add table headers going cell by cell.
    oSheet.Cells[1, 1] = "First Name";
    oSheet.Cells[1, 2] = "Last Name";
    oSheet.Cells[1, 3] = "Full Name";
    oSheet.Cells[1, 4] = "Salary";

    // Create an array to multiple values at once.
    string[,] saNames = new string[5,2];

    saNames[0, 0] = "John";
    saNames[0, 1] = "Smith";
    saNames[1, 0] = "Tom";
    saNames[1, 1] = "Brown";
    saNames[2, 0] = "Sue";
    saNames[2, 1] = "Thomas";
    saNames[3, 0] = "Jane";
    saNames[3, 1] = "Jones";
    saNames[4, 0] = "Adam";
    saNames[4, 1] = "Johnson";

    //Fill A2:B6 with an array of values (First and Last Names).
    oSheet.get_Range("A2", "B6").Value2 = saNames;

    //Fill D2:D6 with a formula(=RAND()*100000) and apply format.
    oRng = oSheet.get_Range("D2", "D6");
    oRng.Formula = "=RAND()*100000";
    oRng.NumberFormat = "$0.00";
    
    oWB.SaveAs(fileLoc, Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookDefault, Type.Missing, Type.Missing,
        false, false, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange,
        Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

    oWB.Close();
    oXL.Quit();
}

如果使用 Excel 互操作,請嘗試以下操作:

using Excel = Microsoft.Office.Interop.Excel;

寫到Excel

public static void WriteToExcel(string filename, string[,] data)
{
    //Write cell value using row number and column number

    //*Note: Excel cells, can also be referenced by name, such as "E2" by using "Range"
    //
    //       All indices in Excel (rowNumber, columnNumber, etc...) start with 1 
    //       The format is: <rowNumber>, <columnNumber>
    //       The top left-most column, is: 1,1


    object oMissing = System.Reflection.Missing.Value;

    Excel.Application excelApp = null;
    Excel.Range range = null;
    Excel.Workbook workbook = null;
    Excel.Worksheet worksheet = null;

    int worksheetCount = 0;

    try
    {
        //create new instance
        excelApp = new Excel.Application();

        //suppress displaying alerts (such as prompting to overwrite existing file)
        excelApp.DisplayAlerts = false;

        //set Excel visability
        excelApp.Visible = true;

        //disable user control while modifying the Excel Workbook
        //to prevent user interference
        //only necessary if Excel application Visibility property = true
        //excelApp.UserControl = false;

        //disable
        //excelApp.Calculation = Excel.XlCalculation.xlCalculationManual;

        //if writing/updating a large amount of data
        //disable screen updating by setting value to false
        //for better performance.
        //re-enable when done writing/updating data, if desired
        //excelApp.ScreenUpdating = false;

        //create new workbook
        workbook = excelApp.Workbooks.Add();

        //get number of existing worksheets
        worksheetCount = workbook.Sheets.Count;

        //add a worksheet and set the value to the new worksheet
        worksheet = workbook.Sheets.Add();

        if (data != null)
        {
            for (int i = 0; i < data.GetLength(0); i++)
            {
                int rowNum = i + 1;

                for (int j = 0; j < data.GetLength(1); j++)
                {
                    int colNum = j + 1;

                    //set cell location that data needs to be written to
                    //range = worksheet.Cells[rowNum, colNum];

                    //set value of cell
                    //range.Value = data[i,j];

                    //set value of cell
                    worksheet.Cells[rowNum, colNum] = data[i,j];
                }
            }
        }

        //enable
        //excelApp.Calculation = Excel.XlCalculation.xlCalculationManual;
        //excelApp.ScreenUpdating = true;

        //save Workbook - if file exists, overwrite it
        workbook.SaveAs(filename, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, Excel.XlSaveAsAccessMode.xlNoChange, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value);

        System.Diagnostics.Debug.WriteLine("Status: Complete. " + DateTime.Now.ToString("HH:mm:ss"));
    }
    catch (Exception ex)
    {
        string errMsg = "Error (WriteToExcel) - " + ex.Message;
        System.Diagnostics.Debug.WriteLine(errMsg);

        if (ex.Message.StartsWith("Cannot access read-only document"))
        {
            System.Windows.Forms.MessageBox.Show(ex.Message + "Please close the workbook, before trying again.", "Error - Unable To Write To Workbook", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
        }
    }
    finally
    {
        if (workbook != null)
        {
            //close workbook
            workbook.Close();

            //release all resources
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(workbook);
        }

        if (excelApp != null)
        {
            //close Excel
            excelApp.Quit();

            //release all resources
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(excelApp);
        }
    }
}

創建一些測試數據:

private string[,] CreateTestData()
{
    string[,] data = new string[6, 4];

    data[0, 0] = "First Name";
    data[0, 1] = "Last Name";
    data[0, 2] = "Full Name";
    data[0, 3] = "Salary";

    data[1, 0] = "John";
    data[1, 1] = "Smith";

    data[2, 0] = "Tom";
    data[2, 1] = "Brown";

    data[3, 0] = "Sue";
    data[3, 1] = "Thomas";

    data[4, 0] = "Jane";
    data[4, 1] = "Jones";

    data[5, 0] = "Adam";
    data[5, 1] = "Johnson";

    return data;
}

更新

這是完整的代碼:

創建一個類(名稱:HelperExcelInterop.cs)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Diagnostics;
using Excel = Microsoft.Office.Interop.Excel;

namespace ExcelInteropTest
{
    public class HelperExcelInterop
    {
        public static void WriteToExcel(string filename, string[,] data)
        {
            //Write cell value using row number and column number

            //*Note: Excel cells, can also be referenced by name, such as "E2" by using "Range"
            //
            //       All indices in Excel (rowNumber, columnNumber, etc...) start with 1 
            //       The format is: <rowNumber>, <columnNumber>
            //       The top left-most column, is: 1,1


            object oMissing = System.Reflection.Missing.Value;

            Excel.Application excelApp = null;
            Excel.Range range = null;
            Excel.Workbook workbook = null;
            Excel.Worksheet worksheet = null;

            int worksheetCount = 0;

            try
            {
                //create new instance
                excelApp = new Excel.Application();

                //suppress displaying alerts (such as prompting to overwrite existing file)
                excelApp.DisplayAlerts = false;

                //set Excel visability
                excelApp.Visible = true;

                //disable user control while modifying the Excel Workbook
                //to prevent user interference
                //only necessary if Excel application Visibility property = true
                //excelApp.UserControl = false;

                //disable
                //excelApp.Calculation = Excel.XlCalculation.xlCalculationManual;

                //if writing/updating a large amount of data
                //disable screen updating by setting value to false
                //for better performance.
                //re-enable when done writing/updating data, if desired
                //excelApp.ScreenUpdating = false;

                //create new workbook
                workbook = excelApp.Workbooks.Add();

                //get number of existing worksheets
                worksheetCount = workbook.Sheets.Count;

                //add a worksheet and set the value to the new worksheet
                worksheet = workbook.Sheets.Add();

                if (data != null)
                {
                    for (int i = 0; i < data.GetLength(0); i++)
                    {
                        int rowNum = i + 1;

                        for (int j = 0; j < data.GetLength(1); j++)
                        {
                            int colNum = j + 1;

                            //set cell location that data needs to be written to
                            //range = worksheet.Cells[rowNum, colNum];

                            //set value of cell
                            //range.Value = data[i,j];

                            //set value of cell
                            worksheet.Cells[rowNum, colNum] = data[i,j];
                        }
                    }
                }

                //enable
                //excelApp.Calculation = Excel.XlCalculation.xlCalculationManual;
                //excelApp.ScreenUpdating = true;

                //save Workbook - if file exists, overwrite it
                workbook.SaveAs(filename, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, Excel.XlSaveAsAccessMode.xlNoChange, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value);

                System.Diagnostics.Debug.WriteLine("Status: Complete. " + DateTime.Now.ToString("HH:mm:ss"));
            }
            catch (Exception ex)
            {
                string errMsg = "Error (WriteToExcel) - " + ex.Message;
                System.Diagnostics.Debug.WriteLine(errMsg);

                if (ex.Message.StartsWith("Cannot access read-only document"))
                {
                    System.Windows.Forms.MessageBox.Show(ex.Message + "Please close the workbook, before trying again.", "Error - Unable To Write To Workbook", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
                }
            }
            finally
            {
                if (workbook != null)
                {
                    //close workbook
                    workbook.Close();

                    //release all resources
                    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(workbook);
                }

                if (excelApp != null)
                {
                    //close Excel
                    excelApp.Quit();

                    //release all resources
                    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(excelApp);
                }
            }
        }
    }
}

在 Form1 上,添加一個按鈕(名稱:btnRun)

雙擊按鈕以添加 Click 事件處理程序。

Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ExcelInteropTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private string[,] CreateTestData()
        {
            string[,] data = new string[6, 4];

            data[0, 0] = "First Name";
            data[0, 1] = "Last Name";
            data[0, 2] = "Full Name";
            data[0, 3] = "Salary";

            data[1, 0] = "John";
            data[1, 1] = "Smith";

            data[2, 0] = "Tom";
            data[2, 1] = "Brown";

            data[3, 0] = "Sue";
            data[3, 1] = "Thomas";

            data[4, 0] = "Jane";
            data[4, 1] = "Jones";

            data[5, 0] = "Adam";
            data[5, 1] = "Johnson";

            return data;
        }

        private void WriteData()
        {
            string[,] data = CreateTestData();

            string filename = System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Test123.xlsx");
            System.Diagnostics.Debug.WriteLine("filename: " + filename);
            HelperExcelInterop.WriteToExcel(filename, data);
        }

        private void btnRun_Click(object sender, EventArgs e)
        {
            WriteData();
        }
    }
}

我建議將Application.Calculation屬性設置為xlCalculationManual值,然后在完成后返回xlCalculationAutomatic

您還可以考慮將Application.ScreenUpdating設置為false ,然后再設置回true

作為一種可能的解決方法,您可以考慮使用Open XML SDK

這很奇怪。 出於好奇,我嘗試運行 user9938 提供的代碼,但得到的結果與 Elruna 相同。 它運行,並且 excel 確實正確打開、保存和關閉,但它沒有在文件中寫入任何內容。 如果代碼已經過測試,是否可以歸結為 excel 中的特定配置?

互操作 Excel 非常慢。 我用超過 50k 行和 10 列的 datagradview 完成了這項工作。 我需要添加一個進度條,因為用戶會認為程序崩潰了。

如果你想更快地運行這項工作,你需要一些其他的 3rd 方庫。 我曾給 EPPlus 一個機會。 它快得像地獄一樣。 另一方面,它很耗內存:您可以在此處找到代碼:

https://stackoverflow.com/a/72763371/17817329

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM