2010-07-06 1 views
3

일부 비즈니스 논리가 포함 된 Excel 시트를 사용합니다 (따라서 비 IT 부서에서 편집하는 경우가 많습니다). 일부 C++ 코드는 동일한 시트에서 VBA로 생성됩니다. 바보입니다. 이 워크 시트에 대한 단위 테스트를 작성하여 모든 사용자를 위해 엄격한 형식을 보장합니다. 예를 들어, 항목은 사전 순으로 정렬되어야합니다. 나는 전에 이런 종류의 일을하지 않았다. 어떤 라이브러리를 사용할 지조차 모르겠다. 내 발을 젖게하려면 "자동 색상, 일반 스타일, Arial, 크기 10"이외의 글꼴이있는 모든 셀을 찾고 싶습니다. 빨간색 또는 굵게 또는 크기 11, 또는 ComicSans 글꼴. 그런 다음 해당 셀이 "비 - 헤더"셀인지 확인하려고합니다. "헤더"셀은 알려진 명명 된 범위의 일부인 셀입니다. 예를 들어, 그러한 셀이 "XYZheaders"라는 명명 된 범위에 속하면 OK입니다. 그렇지 않다면, 문제가있는 모든 셀에 대해 "D25"와 같이 사람이 읽을 수있는 것이 가장 이상적이며, 문제가 색상, 글꼴 유형, 스타일 또는 크기인지 여부를 나타낼 수있는 셀 좌표를보고하고자합니다. .Excel 파일의 비 머리글 셀이 굵게 또는 기울임 꼴인지 테스트하는 방법

편집 :.. 나는 완전한 C#을 샘플을 찾고 있기 때문에 난 그냥이 질문에 현상금을 넣어 당신이 내 질문에 모호한이라고 생각하면 질문 마십시오

답변

3

여기 내 해결책이 있습니다. 일부 Excel 2007 파일 (.xlsx)로 테스트했습니다. 이 프로그램은 VS 2010 (.NET 4를 목표로 함)을 사용하여 Microsoft.CSharp, Microsoft.Office.Interop.Excel, System 및 System.Core의 네 가지 참조를 사용하여 빌드 할 수 있습니다.

.NET 4를 사용하면 Excel에서 작업하기가 약간 쉬워집니다.

어쨌든 여기에 코드입니다 :

using System; 
using System.Collections.Generic; 
using System.Linq; 
using Excel = Microsoft.Office.Interop.Excel; 

namespace ExcelTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Excel.Application excelapplication = null; 
      Excel.Workbook workbook = null; 

      try 
      { 
       excelapplication = new Excel.Application(); 
       workbook = excelapplication.Workbooks.Open(args[0]); 
       var errors = new Dictionary<string, List<string>>(); 
       foreach (Excel.Worksheet sheet in workbook.Sheets) 
       { 
        int rowCount = sheet.UsedRange.Cells.Rows.Count; 
        int colCount = sheet.UsedRange.Cells.Columns.Count; 
        var usedCells = sheet.UsedRange.Cells; 

        for (int i = 1; i <= rowCount; i++) 
        { 
         for (int j = 1; j <= colCount; j++) 
         { 
          Excel.Range range = usedCells[i, j]; 
          List<string> cellErrors; 
          if (HasNonDefaultFont(range, out cellErrors)) 
          { 
           if (!IsHeaderCell(workbook, range)) 
           { 
            string cellDisplayTitle = String.Format("{0}!{1}", sheet.Name, range.Address); 
            errors[cellDisplayTitle] = cellErrors; 
           } 
          } 
         } 
        } 
       } 
       ReportErrors(errors); 
      } 
      finally 
      { 
       if (workbook != null) 
        workbook.Close(); 
       if (excelapplication != null) 
        excelapplication.Quit(); 
      } 
     } 

     static bool HasNonDefaultFont(Excel.Range range, out List<string> differences) 
     { 
      differences = new List<string>(); 

      if (range.Font.Color != 0.0) 
       differences.Add("Has font-color"); 

      if (range.Font.Bold) 
       differences.Add("Is bold"); 

      if (range.Font.Italic) 
       differences.Add("Is italic"); 

      if (range.Font.Underline != (int)Microsoft.Office.Interop.Excel.XlUnderlineStyle.xlUnderlineStyleNone) 
       differences.Add("Is underline"); 

      if (range.Font.Strikethrough) 
       differences.Add("Is strikethrough"); 

      if (range.Font.Name != "Arial") 
       differences.Add(String.Format("Font is {0}", range.Font.Name)); 

      if (range.Font.Size != 10) 
       differences.Add(String.Format("Font size is {0}", range.Font.Size)); 

      return differences.Count != 0; 
     } 

     static bool IsHeaderCell(Excel.Workbook workbook, Excel.Range range) 
     { 
      // Look through workbook names: 
      foreach (Excel.Name namedRange in workbook.Names) 
      { 
       if (range.Parent == namedRange.RefersToRange.Parent && range.Application.Intersect(range, namedRange.RefersToRange) != null) 
        return true; 
      } 

      // Look through worksheet-names. 
      foreach (Excel.Name namedRange in range.Worksheet.Names) 
      { 
       if (range.Parent == namedRange.RefersToRange.Parent && range.Worksheet.Application.Intersect(range, namedRange.RefersToRange) != null) 
        return true; 
      } 
      return false; 
     } 

     static void ReportErrors(Dictionary<string, List<string>> errors) 
     { 
      if (errors.Count > 0) 
      { 
       Console.WriteLine("Found the following errors:"); 
       Console.WriteLine("---------------------------------"); 
       Console.WriteLine("{0,-15} | Error", "Cell"); 
       Console.WriteLine("---------------------------------"); 
      } 

      foreach (KeyValuePair<string, List<string>> kv in errors) 
       Console.WriteLine("{0,-15} | {1}", kv.Key, kv.Value.Aggregate((e, s) => e + ", " + s)); 
     } 
    } 
} 

이 프로그램은 첫 번째 인수로 엑셀 파일의 이름을 가정합니다. 이 파일이 열리고 각 셀은 다른 글꼴 기준에 대해 테스트됩니다. "non-default-font"가있는 셀은 ranged에 대해 테스트되고이 범위를 벗어나는 셀은 콘솔에 출력됩니다.

평상시처럼 프로그램에 오류 처리 기능을 추가해야합니다. 그러나이 기능을 시작하면 좋을 것입니다.

3

이 트릭을 할해야 새로운 범위 이름을 입력해도이 함수가 포함 된 셀은 다시 계산되지 않습니다 (범위 이름을 만든 후 F9).

Option Explicit 

Public Function IsDataCellBoldOrItalic() As Boolean 
    Dim rngName As Name 
    Dim intersectRange As Name 

    For Each rngName In ActiveWorkbook.Names 
     If Not Intersect(rngName.RefersToRange, Application.ThisCell) Is Nothing Then 
      IsDataCellBoldOrItalic = False 
      Exit Function 
     End If 
    Next 

    ''# Now we know we are not in a "header" cell 
    IsDataCellBoldOrItalic = Application.ThisCell.Font.Bold Or Application.ThisCell.Font.Italic 

End Function 
+0

멋지다. 이것은 보통'VB.Net'인가? 나는 이것을'C#'로 쉽게 번역 할 수 있다고 생각한다. –

+0

@Hamish : 통합 문서 내에서 실행할 VBA입니다. – technomalogical

+0

흠 ... 나는 이것을 사용할 수 있다고 생각하지만 Excel 파일을로드하고 분석하는 C# 코드를 선호합니다. –