programing

마이크로소프트(MS.Office.Interop.엑셀은 매우 느리다.

elecom 2023. 4. 18. 21:43
반응형

마이크로소프트(MS.Office.Interop.엑셀은 매우 느리다.

1200 X 800 매트릭스(index Matrix)를 표준 Microsoft를 사용하여 Excel 파일로 내보냅니다.Office.Interop.Excel. 앱은 매우 느립니다.(100 x 100 매트릭스에서도) 텍스트 파일로 내보내면 거의 즉시 작동합니다.엑셀 파일로 더 빨리 내보낼 수 있는 방법은 없나요?

제 코드는 다음과 같습니다.

        Excel.Application xlApp=new Excel.Application();
        Excel.Workbook xlWorkBook;
        Excel.Worksheet xlWorkSheet;
        object misValue = System.Reflection.Missing.Value;

        //xlApp = new Excel.ApplicationClass();
        xlWorkBook = xlApp.Workbooks.Add(misValue);

        xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
        for (int i = 0; i < 800; i++)   //h
            for (int j = 0; j < 1200; j++)
                xlWorkSheet.Cells[i+1,j+1] =indexMatrix[i][j];


        xlWorkBook.SaveAs("C:\\a.xls", Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);
        xlWorkBook.Close(true, misValue, misValue);
        xlApp.Quit();

        releaseObject(xlWorkSheet);
        releaseObject(xlWorkBook);
        releaseObject(xlApp);

        MessageBox.Show("Excel file created , you can find the file c:\\csharp-Excel.xls");

개별 셀을 업데이트하고 있습니다.그건 아주 느릴 거야.생각해 보면 셀을 갱신할 때마다 RPC 콜이 Excel 프로세스에 마셜링됩니다.

현재 1200 x 800 = 960,000개의 교차 프로세스 호출 대신 단일 문(크로스 프로세스 호출 1개)에서 동일한 차원의 Excel 범위에 2차원 값 배열을 할당하는 것이 훨씬 빠릅니다.

예를 들어 다음과 같습니다.

// Get dimensions of the 2-d array
int rowCount = indexMatrix.GetLength(0);
int columnCount = indexMatrix.GetLength(1);
// Get an Excel Range of the same dimensions
Excel.Range range = (Excel.Range) xlWorkSheet.Cells[1,1];
range = range.get_Resize(rowCount, columnCount);
// Assign the 2-d array to the Excel Range
range.set_Value(Excel.XlRangeValueDataType.xlRangeValueDefault, indexMatrix);

실제로, 전문적으로 말하면, 상기의 코드(.)에는 3개의 크로스 프로세스 콜이 있습니다.셀(.get_Resize 및 .set_Value)과 코드(.set_Value)에는 반복마다 2개의 콜이 있습니다.셀이 취득되어 암묵적인 .set_Value)가 합계 1200 x 800 x 2 = 1,920,000이 됩니다.

★★★ range.get_Resize ★★★★★★★★★★★★★★★★★」range.set_Value이 게시물이 처음 작성되었을 때 사용하던 이전 버전의 Excel interop 라이브러리에 필요했습니다.엔 이렇게 쓰잖아요.range.Resize ★★★★★★★★★★★★★★★★★」range.Value@The1nk 。

Excel interop은 결코 빠르지 않을 것입니다.기본적으로 Excel 어플리케이션의 인스턴스를 리모트 컨트롤 하는 것입니다.CSV 파일을 작성한 후 Excel interop을 사용하여 이 파일을 .xls 또는 .xlsx 파일로 변환하면 더 성공할 수 있습니다.

저도 매우 큰 엑셀 파일을 읽을 때 비슷한 문제가 있었고 인터옵션을 사용했을 때 2시간 이상 걸렸습니다.

ClosedXml을 사용해보니 10초도 걸리지 않았습니다.Closed Xml

// To loop 
Sheet.Row(y).Cell(x).Value

또한 엑셀이 설치되어 있지 않으면 interop은 서버에서 작동하지 않습니다.ClosedXml은 Excel을 설치할 필요가 없습니다.

ScreenUpdating에, "데이터를 쓰기 전에"Application.ScreenUpdating = FALSE 후, 코드 「」의 에 됩니다.= TRUE

Value 2를 사용하여 고속화, 데이터 입력 전에 Excel 표시

ClosedXML은 기적입니다. 훨씬 더 빠르고 쉽게 사용할 수 있습니다.

var workbook = new XLWorkbook();//create the new book

var worksheet = workbook.Worksheets.Add("Computer Install");// Add a sheet
worksheet.Cell(1,1).Value = "PC Name";// (Row, column) write to a cell

workbook.SaveAs(@"LIC documents.xlsx");// Save the book

nu Get 패키지를 사용하여 설치합니다.https://www.nuget.org/packages/ClosedXML

답장이 좀 늦었네요 죄송합니다.프로젝트를 진행 중이었는데 상호 운용 엑셀을 사용해야 했습니다.그리고 데이터가 너무 커서 interop excel로 1분 이상 걸렸어요.데이터 뷰의 모든 내용을 클립보드에 복사하고, interop 엑셀을 사용하여 엑셀 워크시트를 열고, 그 내용을 엑셀에 붙여넣는 다른 방법을 시도했습니다.1초도 걸리지 않고 데이터를 완벽하게 내보냅니다.

문자열에 대한 DataGridView:

    var newline = System.Environment.NewLine;
    var tab = "\t";
    var clipboard_string = "";

    foreach (DataGridViewRow row in dgProjeler.Rows)
    {
        for (int i = 0; i < row.Cells.Count; i++)
        {
            if (i == (row.Cells.Count - 1))
                clipboard_string += row.Cells[i].Value + newline;
            else
                clipboard_string += row.Cells[i].Value + tab;
        }
    }

문자열을 클립보드에 복사합니다.

        Clipboard.SetText(clipboard_string);

그리고 워크시트를 열고 내용을 붙여넣습니다.

        Excel.Application app = new Excel.Application();
        app.Visible = true;
        Excel.Workbook wb = app.Workbooks.Add(1);
        Excel.Worksheet ws = (Excel.Worksheet)wb.Worksheets[1];
        // changing the name of active sheet
        ws.Name = "Exported from gridview";

        ws.Rows.HorizontalAlignment = HorizontalAlignment.Center;
        app.ActiveWindow.Activate();


        ws.Activate();
        ws.Paste();

        ws.Cells.EntireColumn.AutoFit();

나한테는 딱 맞아, 아직도 해결책을 찾지 못한 사람들에게 도움이 됐으면 좋겠어.

여기에는 3가지 방법이 있으며, 그 중 2가지는 다른 사람의 답변에 기재되어 있습니다.

  1. excel 범위 값을 2D 어레이로 직접 설정합니다.
  2. CSV 파일에 데이터를 쓴 후 interop을 사용하여 CSV 파일을 xls 또는 xlsx 파일로 저장합니다.
  3. CSV 파일에 데이터를 쓴 후 데이터 연결 기능을 사용하여 CSV를 데이터 소스로 사용하고 데이터를 Import합니다.

위의 세 가지 방법 모두 매우 빠릅니다.9만 행, 100열 크기의 데이터를 6초 정도면 쓸 수 있습니다.

추신. 하지만 그들은 테두리, 글꼴 스타일, 색상, 셀 병합 등의 데이터를 포맷하는 데 있어 제 문제를 해결하지 못했습니다.

언급URL : https://stackoverflow.com/questions/3989122/microsoft-office-interop-excel-really-slow

반응형