2010-02-22 3 views
7

엑셀 워크 시트에 전체 표를 쓸 때 개별 셀에 쓰는 대신 한 번에 전체 Range로 작업하는 것이 좋습니다. 그러나 Excel로 내보낼 배열을 채우는 형식을 지정하는 방법이 있습니까?Excel.Range.set_Value()로 개별 셀의 서식을 지정하는 방법

는 여기에 내가 지금 무엇을 :

object MissingValue = System.Reflection.Missing.Value; 
Excel.Application excel = new Excel.Application(); 
int rows = 5; 
int cols = 5; 
int someVal; 

Excel.Worksheet sheet = (Excel.Worksheet)excel.Workbooks.Add(MissingValue).Sheets[1]; 
Excel.Range range = sheet.Range("A1", sheet.Cells(rows,cols)); 
object[,] rangeData = new object[rows,cols]; 
for(int r = 0; r < rows; r++) 
{ 
    for(int c = 0; c < cols; c++) 
    { 
     someVal = r + c; 
     rangeData[r,c] = someVal.ToString(); 
    } 
} 
range.set_Value(MissingValue, rangeData); 

지금은 그 숫자의 몇 퍼센트로 포맷 할을한다고 가정. 셀 단위로 돌아가 포맷팅을 변경할 수는 있지만 하나의 Range.set_Value() 호출을 사용하는 전체 목적을 상쇄하는 것 같습니다. rangeData [,] 구조체에 서식 정보가 포함되도록하면 set_Value()를 호출 할 때 셀이 원하는 방식으로 서식이 지정됩니다.

명확히하기 위해 전체 Excel.Range 개체의 형식을 설정할 수 있음을 알고 있습니다. 내가 원하는 건 내부 루프에 지정된 각 셀에 대해 지정된 다른 형식을 지정하는 것입니다.

답변

2

그래서 지금까지 내가 찾은 최고의 "해결책"이 있습니다. 그것은 내가 찾고 있던 너바나가 아니지만 각 셀의 형식을 개별적으로 설정하는 것보다 훨씬 빠릅니다.

// 0-based indexes 
static string RcToA1(int row, int col) 
{ 
    string toRet = ""; 
    int mag = 0; 
    while(col >= Math.Pow(26, mag+1)){mag++;} 
    while (mag>0) 
    { 
     toRet += System.Convert.ToChar(64 + (byte)Math.Truncate((double)(col/(Math.Pow(26,mag))))); 
     col -= (int)Math.Truncate((double)Math.Pow(26, mag--)); 
    } 
    toRet += System.Convert.ToChar(65 + col); 
    return toRet + (row + 1).ToString(); 
} 

static Random rand = new Random(DateTime.Now.Millisecond); 
static string RandomExcelFormat() 
{ 
    switch ((int)Math.Round(rand.NextDouble(),0)) 
    { 
     case 0: return "0.00%"; 
     default: return "0.00"; 
    } 
} 


struct ExcelFormatSpecifier 
{ 
    public object NumberFormat; 
    public string RangeAddress; 
} 

static void DoWork() 
{ 
    List<ExcelFormatSpecifier> NumberFormatList = new List<ExcelFormatSpecifier>(0); 

    object[,] rangeData = new object[rows,cols]; 
    for(int r = 0; r < rows; r++) 
    { 
     for(int c = 0; c < cols; c++) 
     { 
      someVal = r + c; 
      rangeData[r,c] = someVal.ToString(); 
      NumberFormatList.Add(new ExcelFormatSpecifier 
       { 
        NumberFormat = RandomExcelFormat(), 
        RangeAddress = RcToA1(rowIndex, colIndex) 
       }); 
     } 
    } 
    range.set_Value(MissingValue, rangeData); 

    int max_format = 50; 
    foreach (string formatSpecifier in NumberFormatList.Select(p => p.NumberFormat).Distinct()) 
    { 
     List<string> addresses = NumberFormatList.Where(p => p.NumberFormat == formatSpecifier).Select(p => p.RangeAddress).ToList(); 
     while (addresses.Count > 0) 
     { 
      string addressSpecifier = string.Join(",",  addresses.Take(max_format).ToArray()); 
      range.get_Range(addressSpecifier, MissingValue).NumberFormat = formatSpecifier; 
      addresses = addresses.Skip(max_format).ToList(); 
     } 
    } 
} 

는 기본적으로 어떤 일이 일어나고 것은 내가 (각 요소는 또한 적용 범위의 A1 스타일 주소를 보유) NumberFormatList의 각 셀의 형식 정보의 목록을 유지하는 것입니다. 원래 아이디어는 워크 시트의 각 고유 한 형식에 대해 Excel.Range를 작성하여 단일 셀에서 해당 범위의 형식을 적용 할 수 있어야한다는 것입니다. 이렇게하면 NumberFormat에 대한 액세스 수가 (잠재적으로) 수천 개에서 몇 개 (사용자가 보유한 다양한 형식)까지 줄일 수 있습니다.

그러나 임의로 긴 셀 목록에서 범위를 구성 할 수 없기 때문에 문제가 발생했습니다. 몇 가지 테스트를 한 결과, 제한이 range.get_Range ("A1, B1, C1, A2, AA5, ....."와 같이) 임의의 범위를 정의하는 데 사용할 수있는 50 ~ 100 개의 셀 사이인지 확인했습니다. 그래서 모든 셀의 목록을 얻은 후에는 한 번에 그 셀을 50 개씩 서식을 적용하는 마지막 while() 루프가 있습니다.

이것은 이상적은 아니지만 그것은 NumberFormat에 대한 액세스 수를 최대 50으로 줄입니다. 중요한 것은 포맷 정보없이 range.set_Value()를 사용하여 스프레드 시트를 작성하는 데 약 3 초가 걸립니다. 시간이 약 10 초로 길어집니다. 각 셀에 형식 정보를 개별적으로 적용하면 스프레드 시트가 작성되는 데 2 ​​분이 걸립니다.

+0

나는 내 자신의 대답을 받아 들였지만, 필자가 결정한 것은 Excel 자동화를 사용하여 파일을 쓰는 것이 나쁜 계획이라는 것입니다. 앞으로 ExcelPackage 라이브러리를 사용하여 직접 작성합니다.xlsx 파일 –

+0

+1 멋진 코드 조각에 대한 하나;) formatSpecifier를 사용하여 셀 범위를 설정할 수 있다는 것을 알지 못했습니다. –

2

당신은 범위에 서식을 적용 한 다음 object[,] 배열 당신의 서식을 지정할 수있는 값으로 채울 수 있습니다

0

당신은

for(int r = 0; r < rows; r++) 
{ 
    for(int c = 0; c < cols; c++) 
    { 
     Excel.Range r2 = sheet.Cells(r, c); 
     r2.xxxx = ""; 
    } 
} 
를 통해 내부 루프 내에서 각각의 셀에 서식을 적용

일단 r2이 있으면 원하는대로 셀 형식을 변경할 수 있습니다.

+0

작업이 완료되었지만 Excel Interop에 대한 호출 수가 절대적으로 최소화되도록 노력하고 있습니다. 내부 루프에 서식을 적용하면 작동하지만 개가 느려질 수 있습니다. –

관련 문제