2009-06-29 3 views
4

C#을 사용하면 Excel 2003에 목록 (즉, List<List<T>>)을 직접 내보낼 수 있습니까?C# 목록을 Excel로 내보내기

큰 텍스트 파일을 구문 분석하고 Excel로 내보내는 중입니다. 한 번에 하나의 셀을 작성하면 너무 많은 오버 헤드가 발생합니다. List<T>을 사용하여 행이나 열의 수를 지정하는 것에 대해 걱정할 필요가 없었습니다.

현재 파일 끝까지 기다린 다음 내 List<List<object>>의 내용을 2 차원 배열에 넣습니다. 그런 다음 배열을 Excel.Range 객체의 값으로 설정할 수 있습니다. 그것은 작동하지만 행이나 열의 수를 신경 쓰지 않고 List of Lists를 취할 수 있어야하며 A1에서 어디로 든 워크 시트에 덤프하면됩니다. 여기

내가 교체하거나에 개선하고자하는 코드 조각입니다 :

object oOpt = System.Reflection.Missing.Value; //for optional arguments 
Excel.Application oXL = new Excel.Application(); 
Excel.Workbooks oWBs = oXL.Workbooks; 
Excel._Workbook oWB = oWBs.Add(Excel.XlWBATemplate.xlWBATWorksheet); 
Excel._Worksheet oSheet = (Excel._Worksheet)oWB.ActiveSheet; 

int numberOfRows = outputRows.Count; 
int numberOfColumns = int.MinValue; 

//outputRows is a List<List<object>> 
foreach (List<object> outputColumns in outputRows) 
{ 
     if (numberOfColumns < outputColumns.Count) 
     { numberOfColumns = outputColumns.Count; } 
} 

Excel.Range oRng = oSheet.get_Range("A1", oSheet.Cells[numberOfRows,numberOfColumns]); 

object[,] outputArray = new object[numberOfRows,numberOfColumns]; 

for (int row = 0; row < numberOfRows; row++) 
{ 
     for (int col = 0; col < outputRows[row].Count; col++) 
     { 
       outputArray[row, col] = outputRows[row][col]; 
     } 
} 

oRng.set_Value(oOpt, outputArray); 

oXL.Visible = true; 
oXL.UserControl = true; 

이 작동하지만, 차라리 배열을 생성하는 중간 단계를 필요없이 Excel로 직접 목록을 사용하십시오 Excel 용입니다. 어떤 아이디어?

답변

8

전략적으로 올바르게 수행하고 있습니다. Joe가 말했듯이 셀 하나 하나를 반복하는 것이 아니라 한 번에 전체 값 배열을 전달하여 셀 값 할당을 실행하는 것이 훨씬 빠릅니다.

Excel은 COM 기반이며 .NET interop을 통해 Excel에서도 작동합니다. interop은 제네릭을 모르는 사이에 불행히도 List <T> 등으로 전달할 수 없습니다. 2 차원 어레이가 실제로 유일한 방법입니다.

그렇다면 코드를 좀 더 관리하기 쉽게 정리할 수있는 몇 가지 방법이 있습니다. 여기에 몇 가지 생각은 다음과 같습니다

(1) .NET 3.0을 사용하는 경우, 당신은에서 코드를 단축 LINQ를 사용할 수 있습니다

int numberOfColumns = int.MinValue; 

foreach (List<object> outputColumns in outputRows) 
{ 
     if (numberOfColumns < outputColumns.Count) 
     { numberOfColumns = outputColumns.Count; } 
} 

한 줄에 :

int numberOfColumns = outputRows.Max(list => list.Count); 

(2) _Worksheet 또는 _Workbook 인터페이스를 사용하지 마십시오. 대신 Worksheet 또는 Workbook을 사용하십시오. 토론을 보려면 여기를 참조하십시오 : Excel interop: _Worksheet or Worksheet?.

(3) Range.Resize 메서드는 C#에서 Range.get_Resize으로 사용하는 것이 좋습니다. 이것은 토스 - 업이지만, 실제로는 범위 크기를 설정하는 것과 같습니다. 그러나 그것은 당신이 알고 싶어 할 것이라고 생각한 어떤 것입니다.예를 들어, 여기 라인 :

Excel.Range oRng = 
    oSheet.get_Range("A1", Type.Missing) 
     .get_Resize(numberOfRows, numberOfColumns); 

(4) 당신은 Application.UserControltrue에를 설정할 필요가 없습니다 :

Excel.Range oRng = oSheet.get_Range("A1", oSheet.Cells[numberOfRows,numberOfColumns]); 

로 변경 될 수 있습니다. 사용자에게 Excel을 보이게하는 것으로 충분합니다. UserControl 속성은 사용자가 생각하는대로 수행하지 않습니다. (도움말 파일 here을 참조하십시오.) 사용자가 Excel을 제어 할 수 있는지 여부를 제어하려면 워크 시트 보호를 사용하거나 집합을 Application.Interactive = false 사용자를 잠글 수 있습니다. (드물지만 좋은 생각입니다.) 그러나 사용자가 Excel을 사용할 수있게하려면 간단하게 표시하는 것으로 충분합니다. 이 도움이 도움이

object oOpt = System.Reflection.Missing.Value; //for optional arguments 
Excel.Application oXL = new Excel.Application(); 
Excel.Workbooks oWBs = oXL.Workbooks; 
Excel.Workbook oWB = oWBs.Add(Excel.XlWBATemplate.xlWBATWorksheet); 
Excel.Worksheet oSheet = (Excel.Worksheet)oWB.ActiveSheet; 

//outputRows is a List<List<object>> 
int numberOfRows = outputRows.Count; 
int numberOfColumns = outputRows.Max(list => list.Count); 

Excel.Range oRng = 
    oSheet.get_Range("A1", oOpt) 
     .get_Resize(numberOfRows, numberOfColumns); 

object[,] outputArray = new object[numberOfRows, numberOfColumns]; 

for (int row = 0; row < numberOfRows; row++) 
{ 
    for (int col = 0; col < outputRows[row].Count; col++) 
    { 
     outputArray[row, col] = outputRows[row][col]; 
    } 
} 

oRng.set_Value(oOpt, outputArray); 

oXL.Visible = true; 

희망 ...

마이크

+0

감사합니다! 우리가 .NET 3.0에 있지는 않지만, 나는 당신의 모든 설명에 감사드립니다. – reverendlarry

+0

문제 없습니다. 도움이 되니 기쁩니다. :-) 항목 # 1만이 .NET 3.0과 관련이 있으며 다른 모든 항목은 모든 .NET Framework에 적용됩니다. LINQ가 3.0으로 이동하는 주요 이유입니다. 모든 코드에 혁명을 일으키지는 않지만 특정 영역에서는 LINQ가 매우 훌륭한 기능입니다. –

+1

고마워요! 이것은 완벽하게 작동, 명확 upvote! 그러나 도움이 될 수있는 하나의 작은 세부; 나는이 코드에'oXL.Quit; '문장을 추가해야했다. 그렇지 않다면 프로세스가 계속 실행되고 특정 시점에 나는 에러를 받기 시작했다. – Soph

1

많은 Excel에 2 차원 배열을 전달하는 것이 한 번에 하나씩 셀을 업데이트하는 것보다 빠릅니다.

목록 목록의 값을 사용하여 2 차원 배열의 개체를 만들고 Excel 범위를 배열의 차원으로 바꾼 다음 range.set_Value를 호출하여 2 차원 배열을 전달합니다.

+0

그게 내가 현재하고있는 일이야. 그러나 배열 대신에'List '을 사용하려고한다면, 중개 배열에 먼저로드하지 않고 데이터를 Excel로 가져 오는 다른 방법이 있을지도 모릅니다. – reverendlarry

0
List<"classname"> getreport = cs.getcompletionreport(); 

var getreported = getreport .Select(c => new { demographic = c.rName); 

희망 :

전반적으로, 마음에 이러한와 함께, 당신의 코드는 다음과 같이 보일 수 있다고 생각

여기서 cs.getcompletionreport()은 참조 클래스 파일입니다. App