[C#] ClosedXML, Spire.XLS 무료 버전 사용 시 AutoFitColumns 버그

2015. 8. 12. 17:32Coders

오랜만에 코딩 이야기 입니다.


선수 항목

ClosedXML - The easy way to OpenXML

Import Data to Excel, Insert a Chart and Convert Excel to PDF


닷넷에서 엑셀 관련 작업이 좀 골때립니다. 고전적인 방식으로는 설치되어 있는 오피스 엑셀 컴포넌트를 로딩하여 Automation 을 통해 엑셀 생성 작업을 하지요.

그런데, Automation으로 엑셀을 생성하고 작업할 경우, 해당 컴포넌트를 제대로 릴리즈 하지 못하거나 하면 난감한 경우가 많이 발생합니다. 그래서 좀 많이 사용되는 무료 컴포넌트가 OpenXML 을 활용한 ClosedXML인데요, 이는 차트나 그런 작업에 있어 좀 코딩 작업이 어렵습니다.


차트 때문에 ClosedXML에서 Spire.XLS 로 넘어간 외국 개발자

Import Data to Excel, Insert a Chart and Convert Excel to PDF


저도 그래서 얼씨구나 해서 nuget을 통해 Spire.XLS 설치를 했습니다. 했는데... 다음과 같이 파일을 생성하면 마지막 시트에 꼭 "Evaluation Warning" 라는 시트를 끼워 넣더군요. 상용 버전을 구매하면 해당 시트가 삽입되지는 않습니다.




아... 이걸 어찌 제거하기 위해 Free 버전이 있는지 찾아봤습니다.

몇 가지 제약사항... 시트 갯수가 제한되어 있고 어쩌고... 그래도 뭐 고난이도의 엑셀 작업은 하지 않으니 뭐 그렇다 치고 그냥 써 봤는데 어? AutoFitColumn 이라는 메서드가 안 먹네요. 좀 찾아보니, 상용버전에서 해당 버그가 수정이 되었다고 합니다.

현재 Free 로 사용 가능한 버전(Ver.7.4)

http://staging.nuget.org/packages/FreeSpire.XLS/


AutoFitColumns 버그가 수정된 버전은 유료입니다.(Ver.7.6.54) - 아, 무료로 사용 가능합니다만, 마지막 에 Evaluation Warning 라는 이름의 시트가 삽입됩니다.

http://staging.nuget.org/packages/Spire.XLS/

Fix the issue where AutoFitColumn method caused the value of some columns displayed incorrectly. - 이런 문구가 들어가 있습니다. 아니 그거 참, 버전 7까지 오면서 컬럼 넓이 맞추기 버그가 남아있었던 거란 말인가. 세상에나.


아... 어찌할까요. 그래서, 그냥 AutoFitColumn 이라는 확장 메서드를 만들었습니다. 써 보니 잘 작동합니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;

using Spire.Xls;

...

public static void ExAutoFitColumns(this CellRange cellRange)
{
	for (int row = cellRange.Row; row <= cellRange.LastRow; row++)
	{
		for (int col = cellRange.Column; col <= cellRange.LastColumn; col++)
		{
			CellRange oneCellRange = cellRange[row, col];
			double oldWidth = oneCellRange.ColumnWidth;
			double newWidth = 0;
			string text = oneCellRange.DisplayedText;
			if (string.IsNullOrWhiteSpace(text) == false)
			{
				using (Font nativeFont = oneCellRange.Style.Font.GenerateNativeFont())
				{
					newWidth = (double)TextRenderer.MeasureText(text, nativeFont).Width;
					newWidth = (newWidth - (double)12) / 7d + 1;	//From Picxels to inches
				}
			}

			if(newWidth > oldWidth)
			{
				oneCellRange.ColumnWidth = newWidth;
				oldWidth = newWidth;
			}
		}
	}
}
올레.
사용할 때에는 다음과 같이 콜.
worksheet.AllocatedRange.ExAutoFitColumns();


20150813 - 버그 발견 :

기본 폰트가 Tahoma 입니다. 그런데, 윈8에는 희한하게도 Tahoma 폰트가 없네요. 그럴 경우, 위와 같은 방법으로 넓이 세팅을 하면, 해당 엑셀파일을 저장하는 시점에 Spire 자체 메서드인 MeasureText 에서 오류가 던져집니다.(이게 웃긴 게, 제가 만든 확장 메서드에서는 오류가 발생하지 않습니다. 세팅 이후, SaveToFile 등의 메서드를 콜 할 때 발생합니다.) 오마이갓. 그래서, 시스템에 설치되어 있는 폰트로 전체 스타일을 세팅해 줘야 합니다. 다음과 같은 방식으로요. 뭐 그냥 데이터테이블 전체를 엑셀파일로 저장하는 메서드를 올리죠.

public string Export(DataTable dt, string fileName)
{
	using (Spire.Xls.Workbook wb = new Workbook())
	{
		//무료 버전에서는 시트 수가 제한됩니다.
		wb.Worksheets.Clear();
		Worksheet ws = wb.Worksheets.Add("데이터결과");

		//기본 컬럼 스타일을 얻어서 스타일 세팅
		CellStyle style = ws.GetDefaultColumnStyle(1);
		//integer 형 등의 데이터가 소숫점이 나타날 경우가 있습니다.
		style.NumberFormat = "0";
		//여기에는 시스템에 존재하는 폰트 이름을 줘야겠지요.
		style.Font.FontName = "맑은 고딕";
		//예상되어지는? 영역에 컬럼 스타일을 지정.
		ws.SetDefaultColumnStyle(1, dt.Columns.Count - 1, style);
		ws.InsertDataTable(dt, true, 1, 1);

		//위에서 작성된 확장 메서드 사용 - AllocatedRange 는 말 그대로 할당된 영역입니다.
		ws.AllocatedRange.ExAutoFitColumns();

		//확장자에 따라 저장 방식 달리함.
		string extension = System.IO.Path.GetExtension(fileName).ToLower();
		if (extension == ".xls")
			wb.SaveToFile(fileName, ExcelVersion.Version97to2003);
		else if (extension == ".pdf")
			wb.SaveToPdf(fileName);
		else
			wb.SaveToFile(fileName, ExcelVersion.Version2007);

		this.ExcelDocViewer(fileName);
	}

	return string.Empty;
}