자세한 내용은 하단의 내 업데이트를 참조하십시오.
때로는 일부 데이터를 Excel 파일 (xlsx 형식)로 출력해야하는 프로젝트가 있습니다. 프로세스는 일반적으로 다음과 같습니다.
사용자가 내 응용 프로그램에서 일부 버튼을 클릭
내 코드는 DB 쿼리를 실행하고 결과를 어떻게 든 처리합니다.
내 코드는 Excel com interop 라이브러리 또는 일부 타사 라이브러리 (예 : Aspose.Cells)를 사용하여 * .xlsx 파일을 생성합니다.
온라인 에서이 작업을 수행하는 방법에 대한 코드 예제를 쉽게 찾을 수 있지만 더 강력한 방법을 찾고 있습니다. 코드를 유지 관리하고 쉽게 이해할 수 있도록 몇 가지 디자인 원칙을 따르도록 코드를 만들고 싶습니다.
xlsx 파일을 생성하려는 초기 시도는 다음과 같습니다.
var wb = new Workbook();
var ws = wb.Worksheets[0];
ws.Cells[0, 0].Value = "Header";
ws.Cells[1, 0].Value = "Row 1";
ws.Cells[2, 0].Value = "Row 2";
ws.Cells[3, 0].Value = "Row 3";
wb.Save(path);
장점 : 많지 않습니다. 작동하므로 좋습니다.
단점 :
- 셀 참조는 하드 코딩되어 있으므로 코드 전체에 마법의 숫자가 흩어져 있습니다.
- 많은 셀 참조를 업데이트하지 않고 열과 행을 추가하거나 제거하기가 어렵습니다.
- 타사 라이브러리를 배워야합니다. 일부 라이브러리는 다른 라이브러리와 같이 사용되지만 여전히 문제가있을 수 있습니다. com interop 라이브러리가 1 기반 셀 참조를 사용하는 반면 Aspose.Cells는 0 기반 셀 참조를 사용하는 문제가있었습니다.
다음은 위에 나열된 단점 중 일부를 해결하는 솔루션입니다. 데이터 테이블을 셀 조작으로 파고 다른 셀 참조를 방해하지 않고 이동하고 변경할 수있는 자체 객체로 취급하고 싶었습니다. 의사 코드는 다음과 같습니다.
var headers = new Block(new string[] { "Col 1", "Col 2", "Col 3" });
var body = new Block(new string[,]
{
{ "Row 1", "Row 1", "Row 1" },
{ "Row 2", "Row 2", "Row 2" },
{ "Row 3", "Row 3", "Row 3" }
});
body.PutBelow(headers);
이 솔루션의 일부로 Blocks 컨테이너를 가져 와서 데이터를 * .xlsx 파일로 출력하는 데 필요한 셀 조작을 수행하는 BlockEngine 객체가 있습니다. 블록 객체에는 서식이 첨부 될 수 있습니다.
장점 :
- 이렇게하면 초기 코드에 있던 대부분의 매직 넘버가 제거됩니다.
- 내가 언급 한 BlockEngine 객체에는 여전히 셀 조작이 필요하지만 많은 셀 조작 코드가 숨겨져 있습니다.
- 스프레드 시트의 다른 부분에 영향을주지 않고 행을 추가하고 제거하는 것이 훨씬 쉽습니다.
단점 :
- 열을 추가하거나 제거하기는 여전히 어렵습니다. 열 2와 3의 위치를 바꾸려면 셀 내용을 직접 바꿔야합니다. 이 경우 편집은 8 회이므로 실수를 할 기회는 8 회입니다.
- 이 두 열에 대한 서식이 있으면 업데이트해야합니다.
- 이 솔루션은 수평 블록 배치를 지원하지 않습니다. 한 블록 만 다른 블록 아래에 놓을 수 있습니다. 물론 가질 수는
tableRight.PutToRightOf(tableLeft)
있지만 tableRight와 tableLeft의 행 수가 다른 경우 문제가 발생할 수 있습니다. 테이블을 배치하려면 엔진이 다른 모든 테이블을 인식해야합니다. 이것은 나에게 불필요하게 복잡해 보인다. - 블록 객체와 BlockEngine을 통한 추상화 계층을 통해 코드가 처음 시도하는 것보다 타사 라이브러리에 덜 밀접하게 연결되어 있지만 여전히 타사 코드를 알아야합니다. 느슨하게 결합 된 다양한 형식 옵션을 지원하려면 많은 코드를 작성해야 할 것입니다. 내 BlockEngine은 큰 혼란입니다.
다른 경로를 취하는 솔루션이 있습니다. 과정은 다음과 같습니다.
보고서 데이터를 가져 와서 선택한 형식으로 xml 파일을 생성합니다.
그런 다음 xsl 변환을 사용하여 xml 파일을 Excel 2003 XML 스프레드 시트 파일로 변환합니다.
거기에서 타사 라이브러리를 사용하여 xml Spreadsheet를 xlsx 파일로 간단히 변환합니다.
비슷한 프로세스를 설명하고 코드 예제가 포함 된 이 페이지 를 찾았습니다 .
장점 :
- 이 솔루션은 거의 세포 조작이 필요하지 않습니다. 대신 xsl / xpath를 사용하여 조작을 수행하십시오. 테이블에서 두 개의 열을 교환하려면 셀 교환이 필요한 다른 솔루션과 달리 xsl 파일의 전체 열을 이동합니다.
- Excel 2003 XML 스프레드 시트를 xlsx 파일로 변환 할 수있는 타사 라이브러리는 여전히 필요하지만 라이브러리가 필요한 모든 것입니다. 써드 파티 라이브러리를 호출하는 데 필요한 코드의 양은 아주 적습니다.
- 이 솔루션은 이해하기 쉽고 가장 적은 양의 코드가 필요하다고 생각합니다.
- 내 XML 형식으로 데이터를 작성하는 코드는 간단합니다.
- xsl 파일은 Excel 2003 XML 스프레드 시트가 복잡하기 때문에 복잡합니다. 그러나 xsl 파일의 출력을 쉽게 확인할 수 있습니다. Excel에서 출력을 열고 오류 메시지를 확인하십시오.
- 샘플 Excel 2003 XML 스프레드 시트 파일을 쉽게 생성 할 수 있습니다. 원하는 xlsx 파일과 같은 스프레드 시트를 만든 다음 Excel 2003 XML 스프레드 시트로 저장하면됩니다.
단점 :
- Excel 2003 XML 스프레드 시트는 특정 기능을 지원하지 않습니다. 예를 들어 열 너비를 자동 맞춤 할 수 없습니다. 머리글이나 바닥 글에는 이미지를 포함 할 수 없습니다. 결과 xlsx 파일을 pdf로 내보내려는 경우 pdf 책갈피를 설정할 수 없습니다. (셀 주석을 사용 하여이 문제를 해결했습니다.). 타사 라이브러리를 사용하여이 작업을 수행해야합니다.
- Excel 2003 XML 스프레드 시트를 지원하는 라이브러리가 필요합니다.
- 11 년 된 MS Office 파일 형식을 사용합니다.
참고 : xlsx 파일은 실제로 xml 파일을 포함하는 zip 파일이지만 xml 형식은 내 목적으로는 너무 복잡해 보입니다.
마지막으로 SSRS와 관련된 솔루션을 살펴 보았지만 내 목적으로는 너무 부풀어 보입니다.
내 첫 질문으로 돌아가서 코드로 Excel 파일을 생성하기위한 좋은 디자인 패턴은 무엇입니까? 나는 몇 가지 해결책을 생각할 수 있지만 이상적인 것으로 생각되는 것은 없습니다. 각각 단점이 있습니다.
업데이트 : 그래서 비슷한 XLSX 파일을 생성하기 위해 BlockEngine 솔루션과 XML Spreadsheet 솔루션을 모두 시도했습니다. 그들의 의견은 다음과 같습니다.
BlockEngine 솔루션 :
- 대안을 고려할 때 너무 많은 코드가 필요합니다.
- 오프셋이 잘못되면 한 블록을 다른 블록으로 덮어 쓰는 것이 너무 쉽다는 것을 알았습니다.
- 원래는 블록 수준에서 서식을 첨부 할 수 있다고 언급했습니다. 블록 내용과 별도로 서식을 지정하는 것보다 낫지 않다는 것을 알았습니다. 내용과 서식을 결합하는 좋은 방법을 생각할 수 없습니다. 그것들을 분리 할 수있는 좋은 방법도 찾을 수 없습니다. 그냥 엉망입니다.
XML 스프레드 시트 솔루션 :
- 지금은이 솔루션으로 갈 것입니다.
- 이 솔루션에는 훨씬 적은 코드가 필요하다는 점을 반복해야합니다. BlockEngine을 Excel 자체로 효과적으로 대체하고 있습니다. 여전히 책갈피 및 페이지 나누기와 같은 기능에 대한 해킹이 필요합니다.
- XML 스프레드 시트 형식은 까다 롭지 만, 약간의 변경 작업을 수행하고 선호하는 Diff 프로그램의 기존 파일과 결과를 쉽게 비교할 수 있습니다. 그리고 일단 당신이 특이성을 알아 낸 후에는 그것을 제자리에 놓고 잊어 버릴 수 있습니다.
- 여전히이 솔루션이 이전 Excel 파일 형식에 의존하고 있다고 걱정합니다.
- 내가 만든 XSLT 파일은 작업하기 쉽습니다. 여기서는 형식을 다루는 것이 BlockEngine 솔루션보다 훨씬 간단합니다.