라이브(저장되지 않은) Excel 데이터와 C# 객체 간의 인터페이스를 위한 가장 빠른 방법
열려 있는 Excel 워크북에서 c# 오브젝트로 데이터를 읽고 쓰는 가장 빠른 방법이 무엇인지 알고 싶습니다.배경은 엑셀에서 사용하고 엑셀에 저장된 데이터를 사용하는 c# 어플리케이션을 개발하고 싶기 때문입니다.
비즈니스 로직은 c# 어플리케이션에 존재하지만 데이터는 Excel 워크북에 존재합니다.사용자는 Excel을 사용하여 Excel 워크북의 버튼을 클릭(또는 유사한 작업을 수행)하여 c# 어플리케이션을 시작합니다.다음으로 c# 어플리케이션은 Excel 워크북에서 데이터를 읽고 데이터를 처리한 후 Excel 워크북에 데이터를 다시 씁니다.
읽어서 Excel 워크북에 다시 써야 하는 데이터 블록이 여러 개 있을 수 있지만, 일반적으로 10행과 20열 등 크기가 비교적 작습니다.따라서는 50,열의 해야 할 수 있습니다.50,000 행은 40,000 행으로 되어 있습니다.
VSTO를 사용하면 비교적 쉽게 말할 수 있지만, 가장 빠른 솔루션(강력하고 우아한 솔루션)을 알고 속도를 알고 싶습니다.솔루션에서는 서드파티 제품을 추천하든 C++를 추천하든 상관없습니다.
명백한 솔루션은 VSTO 또는 interop을 사용하고 있지만 현재 데이터를 읽기 위해 사용하고 있는 VBA와 비교하여 성능이 어떤지 또는 다른 솔루션이 있는지 알 수 없습니다.
이는 전문가 교환소에 게시된 것으로 VSTO가 VBA보다 상당히 느리지만 몇 년 전 일이기 때문에 성능이 향상되었는지는 알 수 없습니다.
http://www.experts-exchange.com/Microsoft/Development/VSTO/Q_23635459.html
감사해요.
이것을 과제로서 Excel과 C# 사이에서 데이터를 셔플하는 가장 빠른 방법은 Excel-DNA - http://excel-dna.net을 사용하는 것입니다(해고:저는 엑셀 DNA를 개발합니다.그래도 사실이야...)
네이티브의 .xll 인터페이스를 사용하기 때문에 VSTO 또는 다른 COM 기반의 애드인 접근법에 의한 COM 통합 오버헤드는 모두 생략됩니다.Excel-DNA를 사용하면 메뉴나 리본 버튼에 연결된 매크로를 만들 수 있습니다.이 버튼은 범위를 읽고 처리하고 Excel의 범위에 다시 씁니다.모두 C#의 네이티브 Excel 인터페이스를 사용합니다.COM 오브젝트는 표시되지 않습니다.
현재 선택 항목을 배열로 만들고 배열 내의 모든 숫자를 제곱하여 셀 A1부터 시작하여 시트 2에 결과를 쓰는 작은 테스트 함수를 만들었습니다.http://excel-dna.net 에서 다운로드 할 수 있는 (무료) Excel-DNA 런타임만 추가하면 됩니다.
C#을 읽어내서 1초 안에 100만 셀 범위를 Excel에 다시 씁니다.이것으로 충분합니까?
기능은 다음과 같습니다.
using ExcelDna.Integration;
public static class RangeTools {
[ExcelCommand(MenuName="Range Tools", MenuText="Square Selection")]
public static void SquareRange()
{
object[,] result;
// Get a reference to the current selection
ExcelReference selection = (ExcelReference)XlCall.Excel(XlCall.xlfSelection);
// Get the value of the selection
object selectionContent = selection.GetValue();
if (selectionContent is object[,])
{
object[,] values = (object[,])selectionContent;
int rows = values.GetLength(0);
int cols = values.GetLength(1);
result = new object[rows,cols];
// Process the values
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
if (values[i,j] is double)
{
double val = (double)values[i,j];
result[i,j] = val * val;
}
else
{
result[i,j] = values[i,j];
}
}
}
}
else if (selectionContent is double)
{
double value = (double)selectionContent;
result = new object[,] {{value * value}};
}
else
{
result = new object[,] {{"Selection was not a range or a number, but " + selectionContent.ToString()}};
}
// Now create the target reference that will refer to Sheet 2, getting a reference that contains the SheetId first
ExcelReference sheet2 = (ExcelReference)XlCall.Excel(XlCall.xlSheetId, "Sheet2"); // Throws exception if no Sheet2 exists
// ... then creating the reference with the right size as new ExcelReference(RowFirst, RowLast, ColFirst, ColLast, SheetId)
int resultRows = result.GetLength(0);
int resultCols = result.GetLength(1);
ExcelReference target = new ExcelReference(0, resultRows-1, 0, resultCols-1, sheet2.SheetId);
// Finally setting the result into the target range.
target.SetValue(result);
}
}
C# 어플리케이션이 스탠드아론 어플리케이션인 경우, 예를 들어 C#에서 C++로 언어를 변경함으로써 실행할 수 있는 최적화에는 부하가 걸리는 크로스프로세스 마셜링이 항상 필요합니다.이 경우 가장 선호하는 언어(C#처럼 들림)를 사용합니다.
그러나 Excel 내에서 실행되는 추가 기능을 사용하려는 경우, 교차 프로세스 호출을 피하고 약 50배 더 빠르게 실행할 수 있습니다.
Excel 내에서 애드인으로 실행하는 경우 VBA가 가장 빠른 옵션 중 하나이지만 COM이 포함되므로 XLL 애드인을 사용하는 C++ 콜이 가장 빠릅니다.그러나 Excel 객체 모델에 대한 호출은 VBA가 여전히 매우 빠릅니다.그러나 실제 계산 속도는 VBA가 완전 컴파일된 코드가 아닌 pcode로 실행되기 때문에 네이티브 코드보다 약 2~3배 느립니다.이것은 매우 나쁘게 들리지만, 일반적인 Excel 애드인 또는 응용 프로그램에 소요되는 실행 시간의 대부분이 Excel 객체 모델에 대한 호출과 관련되어 있기 때문에 VBA와 완전히 컴파일된 COM 애드인의 속도는 약 5~15%에 불과하며, 이는 눈에 띄지 않습니다.
VB 6.0은 컴파일된 COM 어프로치로 Excel 이외의 콜의 경우 VBA보다 2~3배 빠르게 실행되지만, 예를 들어 32비트 또는 64비트를 실행하도록 설치할 수 있는 Office 2010을 설치하는 경우 VB 6.0은 약 12년 전에 64비트 모드로 실행되지 않습니다.64비트 Excel은 현재 사용량은 적지만 사용량은 증가할 것이기 때문에 VB 6.0은 피하고 싶습니다.
C#(Excel 애드인으로 실행 중인 경우 Excel 객체모델에 대한 콜은 VBA만큼 빠르게 실행되며 Excel 이외의 콜은 VBA보다 2~3배 빠르게 실행됩니다(심 없이 실행 중인 경우).다만, Microsoft 에서는, 예를 들면, COM Shim Wizard 를 사용해 완전하게 Shim 를 실행하는 것을 추천합니다.Shim을 적용함으로써 Excel은 고객님의 코드(장애가 있는 경우)로부터 보호되며, 고객님의 코드는 문제를 일으킬 수 있는 다른 서드파티 애드인으로부터 완전히 보호됩니다.단, Shimed 솔루션은 별도의 AppDomain 내에서 실행되므로 실행 속도가 약 40배 빨라야 합니다.이것은 많은 컨텍스트에서 매우 두드러집니다.
VSTO(Visual Studio Tools for Office)를 사용하는 애드인은 자동으로 심 내에 로드되고 별도의 AppDomain 내에서 실행됩니다.VSTO를 사용하는 경우 이를 피할 수 없습니다.따라서 Excel 객체모델에 대한 콜에서도 약 40배의 실행속도가 저하됩니다.VSTO는 매우 풍부한 Excel 애드인을 만들기 위한 훌륭한 시스템이지만, 실행 속도는 고객님의 어플리케이션과 같은 어플리케이션의 약점입니다.
ExcelDna는 C# 코드를 사용할 수 있는 무료 오픈소스 프로젝트이며, C++ 코드를 사용하는 XLL 애드인으로 변환됩니다.즉, ExcelDna는 C# 코드를 해석하여 필요한 C++ 코드를 만듭니다.직접 사용해 본 적은 없지만, 공정에 대해 잘 알고 있어 매우 인상적입니다.ExcelDna는 그것을 사용하는 사람들로부터 매우 좋은 평가를 받는다.[편집: Govert의 코멘트에 따라 다음과 같은 수정에 주의해 주십시오.안녕하세요.Excel-Dna 구현을 명확하게 하기 위해 작은 수정을 추가합니다.모든 관리 대상 어셈블리에서 리플렉션을 사용하여 런타임에 동작합니다.컴파일 전 단계나 C++ 코드 생성은 없습니다. 또한 Excel-Dna가 사용되는데도.NET, Excel과 대화할 때 COM 인터op을 사용할 필요가 없습니다.원어민 인터페이스는 에서 직접 사용할 수 있습니다.NET(단, 필요에 따라서 COM 를 사용할 수도 있습니다). 이를 통해 고성능 UDF 및 매크로가 가능해집니다." – Govert]
Add-in Express도 살펴볼 수 있습니다.무료는 아니지만 C#을 코드화할 수 있고 솔루션을 별도의 AppDomain으로 쉬밍할 수 있지만 실행 속도는 매우 빠르다고 생각합니다.실행 속도를 올바르게 이해하고 있다면 Add-in Express가 어떻게 이 작업을 수행하는지 알 수 없지만 FastPath AppDomain 마샬링이라는 기능을 이용하고 있을 수 있습니다.하지만 Add-in Express에 대해 잘 모르기 때문에 이 부분에 대해서는 언급하지 마십시오.그래도 한번 확인해 보시고 직접 조사해보시기 바랍니다.[편집: Charles Williams의 답변을 읽어보면 Add-in Express는 COM API와 C API 모두에 액세스할 수 있는 것 같습니다. 또한 Govert는 Excel DNA가 COM과 Fastler C API 모두에 액세스할 수 있도록 한다고 말합니다. 따라서 두 가지를 모두 체크하여 ExcelDna와 비교하는 것이 좋습니다.]
Add-in Express와 ExcelDna에 대해 알아보시기 바랍니다.어느 쪽의 어프로치에서도, 가장 익숙한 C# 를 사용해 코드를 작성할 수 있습니다.
또 다른 주요 문제는 전화를 거는 방법입니다.예를 들어, Excel은 앞뒤로 전달되는 모든 데이터를 배열로 처리할 때 매우 빠릅니다.이것은 개별적으로 셀을 루프하는 것보다 훨씬 효율적입니다.예를 들어, 다음 코드는 Excel을 사용합니다.Range.set_Value Accessor 메서드는 10 x 10의 값 배열을 10 x 10의 셀 범위에 한 번에 할당합니다.
void AssignArrayToRange()
{
// Create the array.
object[,] myArray = new object[10, 10];
// Initialize the array.
for (int i = 0; i < myArray.GetLength(0); i++)
{
for (int j = 0; j < myArray.GetLength(1); j++)
{
myArray[i, j] = i + j;
}
}
// Create a Range of the correct size:
int rows = myArray.GetLength(0);
int columns = myArray.GetLength(1);
Excel.Range range = myWorksheet.get_Range("A1", Type.Missing);
range = range.get_Resize(rows, columns);
// Assign the Array to the Range in one shot:
range.set_Value(Type.Missing, myArray);
}
엑셀도 마찬가지로 사용할 수 있습니다.Range.get_Value 접근자 메서드를 사용하여 범위로부터 값 배열을 한 번에 읽을 수 있습니다.이것을 실행한 후 어레이 내의 값을 루핑하는 것이 범위의 셀 내의 값을 개별적으로 루핑하는 것보다 훨씬 빠릅니다.
어레이 사용에 관한 Mike Rosenblum의 코멘트에 덧붙여, 지금까지의 어프로치(VSTO+어레이)를 사용해 측정했을 때, 실제의 판독 속도 자체는 밀리초 이내였습니다.읽기/쓰기 전에 이벤트 처리 및 화면 업데이트를 해제하고 작업이 완료된 후 다시 활성화해야 합니다.
C#을 사용하면 Excel VBA 자체와 동일하게 1개의 기반 어레이를 생성할 수 있습니다.이는 특히 VSTO에서도 Excel에서 어레이를 추출할 때 유용합니다.레인지 오브젝트(어레이는 1 베이스)이므로 Excel 지향 어레이를 1 베이스로 유지하면 어레이가 1 베이스인지 제로 베이스인지를 항상 확인할 필요가 없습니다.(어레이 내의 컬럼 위치가 중요한 경우 0 베이스 어레이와 1 베이스 어레이를 처리해야 하는 것은 매우 어려운 일입니다).
일반적으로 엑셀을 읽는다.어레이의 범위는 다음과 같습니다.
var myArray = (object[,])range.Value2;
Mike Rosenblum의 어레이 쓰기에서는 다음과 같은1 베이스 어레이가 사용되고 있습니다.
int[] lowerBounds = new int[]{ 1, 1 };
int[] lengths = new int[] { rowCount, columnCount };
var myArray =
(object[,])Array.CreateInstance(typeof(object), lengths, lowerBounds);
var dataRange = GetRangeFromMySources();
// this example is a bit too atomic; you probably want to disable
// screen updates and events a bit higher up in the call stack...
dataRange.Application.ScreenUpdating = false;
dataRange.Application.EnableEvents = false;
dataRange = dataRange.get_Resize(rowCount, columnCount);
dataRange.set_Value(Excel.XlRangeValueDataType.xlRangeValueDefault, myArray);
dataRange.Application.ScreenUpdating = true;
dataRange.Application.EnableEvents = true;
Excel 데이터에 대한 가장 빠른 인터페이스는 C API입니다.링크되어 있는 제품은 많이 있습니다.이 인터페이스를 사용하는 NET에서 Excel로.
이를 위해 마음에 드는 제품은 Excel DNA(자유 오픈소스)와 Addin Express(CAPI와 COM 인터페이스를 모두 사용할 수 있는 상용 제품)입니다.
우선, 솔루션은 Excel UDF(사용자 정의 함수)가 될 수 없습니다.매뉴얼에서는 "Excel UDF는 최종 사용자가 공식에 사용할 수 있도록 Excel에서 커스텀 함수를 구축하는 데 사용됩니다."라고 정의하고 있습니다.좀 더 좋은 정의를 제안해주시면 감사하겠습니다.
이 정의에서는 UDF가 UI에 버튼을 추가하거나(XLL이 CommandBar UI를 변경할 수 있음을 알고 있습니다), 키보드숏컷 및 Excel 이벤트를 대행 수신할 수 없습니다.
즉, ExcelDNA는 XLL 애드인을 개발하기 위한 것이므로 범위를 벗어납니다.XLL 애드인과 Excel Automation 애드인을 개발할 수 있기 때문에 Excel이 대상으로 하는 Add-in Express의 기능에도 동일하게 적용됩니다.
Excel 이벤트를 처리해야 하므로 솔루션이 독립형 애플리케이션일 수 있지만 이러한 접근 방식에는 분명한 한계가 있습니다.유일한 방법은 COM 애드인을 만드는 것입니다.Excel 이벤트를 처리하고 Excel UI에 커스텀을 추가할 수 있습니다.다음의 3가지 가능성이 있습니다.
- VSTO
- 애드인 익스프레스(COM 애드인 기능)
- 공유 추가 기능(VS에서 새 프로젝트 대화 상자의 해당 항목 참조)
Excel COM 애드인 개발에 대해 이야기할 경우 위의 3가지 툴은 비주얼 디자이너, 쉬밍 등 다양한 기능을 제공합니다.그러나 Excel Object Model에 접속하는 속도에는 차이가 없다고 생각합니다.예를 들어, 기본 AppDomain에서 COM 개체를 가져오는 것과 다른 AppDomain에서 동일한 COM 개체를 가져오는 것이 왜 다른지 알 수 없습니다.참고로 공유 애드인을 만든 후 COM Shim Wizard를 사용하여 Shiming이 작동 속도에 영향을 미치는지 확인할 수 있습니다.
속도 II어제 쓴 것처럼 "일부 셀의 읽기 및 쓰기 속도를 높이는 가장 좋은 방법은 Excel 변수를 만드는 것입니다.해당 범위를 참조하는 범위 유형을 선택한 다음 변수의 Value 속성에서 배열을 읽거나 씁니다."그러나 Francesco의 설명과는 달리 VSTO에 기인하지 않습니다.이것은 Excel 객체 모델의 특징입니다.
속도 III가장 빠른 Excel UDF는 어느 것도 아닌 네이티브 C++로 쓰여집니다.NET 언어ExcelDNA와 Add-in Express의 XLL 애드인의 속도를 비교한 적이 없기 때문에 큰 차이는 없다고 생각합니다.
요약하자면.Add-in Express, VSTO 또는 Shared Add-in 기반의 COM 애드인은 Excel 셀을 같은 속도로 읽고 쓸 수 있습니다.누군가 이 진술을 반증해 주었으면 좋겠다.
이제 다른 질문들을 해보겠습니다.VSTO에서는 Office 2000-2010을 지원하는 COM 애드인을 개발할 수 없습니다.Office 2003-2010을 완전히 지원하려면 3개의 다른 코드베이스와 2개 이상의 Visual Studio 버전이 필요합니다.Excel 2003용 VSTO 기반 애드인을 도입하려면 강한 긴장감과 운이 있어야 합니다.Add-in Express를 사용하면 단일 코드베이스의 모든 Office 버전에 대해 COM 애드인을 작성할 수 있습니다.Add-in Express는 Excel 2000-2010(32비트 및 64비트)에 애드인을 설치할 수 있는 셋업 프로젝트를 제공합니다.[전개가 온보드 되면]을 클릭합니다.
VSTO는 하나의 영역에서 Add-in Express를 능가합니다. 즉, 문서 수준의 추가 기능을 만들 수 있습니다.의 워크북 또는 템플릿을 상상해 보십시오.그 배후에 있는 NET 코드. 그러나, 그러한 것을 도입하는 것이 악몽이라고 해도, 나는 놀라지 않을 것이다.
Excel 이벤트에 대해서.Excel 이벤트는 모두 MSDN에 나열됩니다(Excel 2007 이벤트 참조).
벨로루시(GMT+2)로부터의 경구,
Andrei Smolin 애드인 Express 팀장
VBA 코드(매크로)를 사용하여 데이터를 수집하고 압축하여 C#에 한 번의 호출로 데이터를 가져옵니다.또, 그 반대도 마찬가지입니다.이것이 가장 퍼포먼스 높은 어프로치가 될 것입니다.
C# 를 사용하는 경우는, 항상 어느 정도의 마샬링을 사용할 필요가 있습니다.VSTO 또는 COM Interop을 사용하는 경우 기본 통신 계층(마샬링 오버헤드)은 동일합니다.
VBA(Visual Basic For Application)에서는 Excel 내의 오브젝트에 대해 직접 작업합니다.따라서 이 데이터에 대한 액세스 속도는 항상 빨라집니다.
하지만 일단 C#에 데이터가 있으면 이 데이터를 훨씬 더 빠르게 처리할 수 있습니다.
VB6 또는 C++ 를 사용하고 있는 경우는, COM 인터페이스도 경유해, 크로스 프로세스 마샬링도 발생합니다.
즉, 크로스 프로세스콜과 마샬링을 최소화하는 방법을 찾고 있습니다.
언급URL : https://stackoverflow.com/questions/3840270/fastest-way-to-interface-between-live-unsaved-excel-data-and-c-sharp-objects
'programing' 카테고리의 다른 글
SQL Server 데이터베이스로 Excel 스프레드시트 열 가져오기 (0) | 2023.04.13 |
---|---|
SQL Server ORDER BY 날짜 및 Null 마지막 (0) | 2023.04.13 |
Python의 목록 내에서 하위 문자열 찾기 (0) | 2023.04.13 |
MVVM Light Toolkit을 사용하여 새 창을 여는 방법 (0) | 2023.04.13 |
Postgres 배열에 값이 있는지 확인합니다. (0) | 2023.04.13 |