컨버터: 가장 간단한 한 줄, 어떤 환경에서도 가장 유연하게
The converter package of Aspose.Cells for Go via C++ Toolkits reduces every “스프레드시트를 다른 형식으로 변환” need to one entry function:
converter.Convert(source, saveOption, sink) error
세 개의 매개변수만 있으며, 각각은 정확히 하나의 질문에 답합니다.
| 매개변수 | 유형 | 답변하는 질문 | 일반적인 값 |
|---|---|---|---|
source | datasource.DataSource | 입력은 어디에서 오는가? | FilePathSource(path), BytesSource(data), NewReaderSource(r) |
saveOption | saveoptions.SaveOption | 출력은 무엇으로, 어떻게 조정하나요? | formats.Get("pdf") 기본값을 이름으로 가져오거나, pdf.New(pdf.WithOnePagePerSheet(true)) 세밀하게 제어하기 위해 |
sink | datasource.DataSink | 출력은 어디로 가나요? | FilePathSink(path), &BytesSink{}, NewWriterSink(w) |
가장 간결한 스타일을 위해서는 세 축 모두 기본값을 사용하고; 가장 유연한 경우에는 각 노브를 개별적으로 조정합니다. 세 축이 독립적이기 때문에 동일한 Convert가 파일, 메모리, HTTP 및 배치 환경에 자연스럽게 맞습니다. (또한 일반 파일→파일 경우를 위한 레거시 원-라이너 ConvertSpreadsheetToFile도 있습니다 — 아래 섹션 1에서 비교합니다.) 이 문서의 나머지 부분은 가장 간결한 방식에서 가장 유연한 방식으로 이동하면서, 다른 API로 전환하지 않고 각 단계마다 이전 스니펫을 확장합니다.
1. 가장 간단한 방법: 하나의 형식에 대한 한 번의 호출
1.1 내장 파일→파일 원-라인 명령: ConvertSpreadsheetToFile
패키지는 고전적인 “이 파일을 저 파일로 변환” 경우를 위한 더 오래된, 훨씬 짧은 엔트리도 제공합니다. 필요한 것은 두 개의 경로뿐입니다:
package main
import (
"log"
"github.com/aspose-cells/aspose-cells-go-cpp-toolkits/v26/core"
"github.com/aspose-cells/aspose-cells-go-cpp-toolkits/v26/converter"
_ "github.com/aspose-cells/aspose-cells-go-cpp-toolkits/v26/register" // registers every output format
)
func main() {
defer core.Cleanup()
// Both ends are files; the output format is inferred from the extension.
if err := converter.ConvertSpreadsheetToFile("input.xlsx", "output.pdf"); err != nil {
log.Fatal(err)
}
}
Deprecated.
ConvertSpreadsheetToFile은(는) 이전 호환성을 위해 유지되는 얇은 래퍼이며, 새로운 코드는 아래의converter.Convert로 향합니다. 파일→파일 경우 두 메서드는 정확히 동일합니다 — 이것이ConvertSpreadsheetToFile이 수행하는 전부입니다.
opt := formats.Get(strings.TrimPrefix(filepath.Ext("output.pdf"), ".")) // "pdf"
converter.Convert(
datasource.FilePathSource("input.xlsx"), // input: a file
opt, // format: taken from the extension
datasource.FilePathSink("output.pdf"), // output: a file
)
ConvertSpreadsheetToFile와 위의 Convert 형태는 동일한 결과를 생성합니다; 차이점은 다음에 비교되는 시나리오입니다.
1.2 권장되는 한 줄 명령: Convert 기본값 사용
package main
import (
"log"
"github.com/aspose-cells/aspose-cells-go-cpp-toolkits/v26/core"
"github.com/aspose-cells/aspose-cells-go-cpp-toolkits/v26/converter"
"github.com/aspose-cells/aspose-cells-go-cpp-toolkits/v26/datasource"
"github.com/aspose-cells/aspose-cells-go-cpp-toolkits/v26/saveoptions/pdf"
)
func main() {
defer core.Cleanup()
if err := converter.Convert(
datasource.FilePathSource("input.xlsx"), // input: a file
pdf.New(), // format: PDF, all defaults
datasource.FilePathSink("output.pdf"), // output: a file
); err != nil {
log.Fatal(err)
}
}
세 개의 모든 옵션은 기본값을 사용합니다: 입력 = 파일, 형식 = pdf.New() (구성 없이), 출력 = 파일. 그것이 “가장 간결한” 형태 — 수동 os.Open/os.Create 없이, 객체 할당 없이, 핸들 닫기 없이; 소스/싱크가 리소스를 관리합니다.
1.3 두 파일→파일 형태 비교
ConvertSpreadsheetToFile(in, out) | converter.Convert(source, opt, sink) | |
|---|---|---|
| 입력 | 파일 경로만 | DataSource는 경로, []byte, 또는 리더 중 하나 |
| 출력 | 파일 경로만 | DataSink는 경로, 바이트 또는 io.Writer 중 하나 |
| 출력 형식 | 항상 확장자를 기반으로 추론되며, 기본값만 사용 | saveOption은 기본값 또는 형식별 조정 |
| 추가 가져오기 | 형식이 등록되어 있어야 함(_ "…/register", 또는 해당 saveoptions/* 서브패키지) | pdf.New()와 같은 생성자를 전달할 경우 필요 없음 |
| 상태 | 사용 중단된 얇은 래퍼(안정적이며 호환성을 위해 유지됨) | 새 코드용으로 문서화된 단일 진입점 |
같은 파일 → 파일 결과, 두 가지 다른 시나리오:
ConvertSpreadsheetToFile— 문자 그대로 두 개의 경로가 있고 대상 형식에 대한 엔진의 기본 설정에 만족합니다. 일회성 변환 스크립트, 마이그레이션 배치 및 테스트 도우미에 이상적입니다. 비용은: 입력, 출력 및 설정이 “파일 경로 + 기본값” 형태를 벗어날 수 없으며 — 그리고 이는 더 이상 사용되지 않습니다.converter.Convert— 동일한 한 줄 코드를 원하지만 세 개 인수 중 어느 것이든 교체 가능해야 합니다: 내일 입력이 업로드된[]byte가 되고, 대상이pdf.WithOnePagePerSheet(true)를 필요로 하거나, 출력이 바로 HTTP 응답으로 가야 할 경우. 이는 섹션 3과 4의 시나리오와 정확히 일치합니다 —Convert로 한 번 작성하고 각 변경은 한 인수 수정으로 처리합니다.
2. 가장 간단한 × N: 모든 32가지 형식에 대한 하나의 함수
다음 단계의 간결함은 대상 형식에 관계없이 같은 함수를 사용하는 것입니다. saveOption을 출력 파일 확장자에서 계산할 수 있기 때문에, 그 추론을 분리하면 “범용 파일 변환기"가 됩니다:
package main
import (
"errors"
"fmt"
"log"
"os"
"path/filepath"
"strings"
"github.com/aspose-cells/aspose-cells-go-cpp-toolkits/v26/core"
"github.com/aspose-cells/aspose-cells-go-cpp-toolkits/v26/converter"
"github.com/aspose-cells/aspose-cells-go-cpp-toolkits/v26/datasource"
toolkiterrors "github.com/aspose-cells/aspose-cells-go-cpp-toolkits/v26/errors"
"github.com/aspose-cells/aspose-cells-go-cpp-toolkits/v26/formats"
_ "github.com/aspose-cells/aspose-cells-go-cpp-toolkits/v26/register" // registers every output format
)
// convert re-saves in as out; the output format is read from out's extension.
// The same code handles every built-in format (pdf/csv/html/md/xlsx/png/…).
// It is exactly what the deprecated ConvertSpreadsheetToFile does internally.
func convert(in, out string) error {
opt := formats.Get(strings.TrimPrefix(filepath.Ext(out), ".")) // ".pdf" -> "pdf"
if opt == nil {
return fmt.Errorf("%w: %q", toolkiterrors.ErrUnsupportedFormat, filepath.Ext(out))
}
return converter.Convert(
datasource.FilePathSource(in), // where the input comes from
opt, // what to produce: decided by the extension
datasource.FilePathSink(out), // where the output goes
)
}
func main() {
defer core.Cleanup()
if len(os.Args) != 3 {
log.Fatalf("usage: %s <input.xlsx> <output.ext>", os.Args[0])
}
if err := convert(os.Args[1], os.Args[2]); err != nil {
if errors.Is(err, toolkiterrors.ErrUnsupportedFormat) {
log.Printf("no registered output format for %q", filepath.Ext(os.Args[2]))
}
log.Fatal(err)
}
fmt.Println("done")
}
사용법은 동일하게 유지되며 — 출력 확장자만 변경됩니다:
$ go run . input.xlsx report.pdf # to PDF
$ go run . input.xlsx report.csv # to CSV
$ go run . input.xlsx report.html # to HTML
$ go run . input.xlsx notes.md # to Markdown
$ go run . input.xlsx sheet.png # to a PNG image
$ go run . input.xlsx legacy.xls # to legacy Excel
그 빈 _ "…/register" import는 무엇인가요?
saveOption을 얻는 방법은 두 가지가 있습니다; 이것은 “most concise” 스타일이 이해해야 하는 유일한 개념입니다:
- 형식 이름으로 레지스트리에서 찾아보기 (
formats.Get): 확장자는formats레지스트리에 존재해야 합니다. 각saveoptions/*서브패키지는 자체init()에서 자신을 등록하지만, 가져올 때만 등록됩니다. 필요한 서브패키지를 하나씩 가져오세요 (pdf만 가져오면 PDF로 변환할 때처럼), 또는 blank-import…/register한 번 하면 모든 32가지 형식을 한 번에 등록합니다 — 위의 “범용 변환기"는 이 한 줄에 의존합니다. - 생성자를 직접 호출 (
pdf.New(),markdown.New()): 레지스트리를 우회하며register를 가져올 필요가 없습니다; 사용하려는 형식당 하나의 import 라인이 필요합니다.
요약하면: formats.Get와 출력 확장자를 통해 해결할 때만 _ "…/register"를 사용하십시오; 생성자를 직접 전달하는 경우 별도의 작업이 필요하지 않습니다. 빈 import는 해가 없으며 공식 예제에 항상 포함되어 있습니다.
3. 가장 유연함: 각 노브를 독립적으로 조정
필요가 “파일을 파일로 기본 설정으로 변환"을 넘어서는 경우, API를 변경하지 않습니다 — 세 개의 Convert 매개변수는 독립적으로 교환할 수 있습니다.
1. 입력 (소스): 파일에서, 메모리로, 모든 스트림으로
datasource.FilePathSource("input.xlsx") // a file on disk
datasource.BytesSource(data) // []byte already in memory (downloads, cached reuse)
datasource.NewReaderSource(r.Body) // any io.Reader (HTTP body, compressed stream, …)
참고: 기본 엔진은 전체 콘텐츠에 대한 임의 접근이 필요하므로
ReaderSource는 첫 번째 접근 시 스트림을 완전히 버퍼링합니다; 이후의 모든Open은 해당 버퍼의 복사본을 제공합니다. HTTP에 대해 안심하고 사용할 수 있지만, 이것이 실제 “스트리밍 중 변환"은 아니라는 점을 알아두세요.
2. 포맷 (saveOption): 기본값 또는 조정됨
| Scenario | Writing style | Why |
|---|---|---|
| 기본 설정이 적용된 일부 형식 | formats.Get("pdf") | 확장자로 조회; 대소문자 구분 없음; nil if unregistered |
| 형식별 옵션이 있는 형식 | pdf.New(pdf.WithOnePagePerSheet(true)) | 함수형 옵션 |
| 기본 설정, 명시적 형식 | ooxml.New() / csv.New() / … | 형식당 인수가 없는 생성자 하나 |
| 사용자 정의 비공개 형식 | formats.Register("fmt", factory) | 레지스트리에 연결 — docs/register.md 참조 |
기능 옵션은 해당 옵션이 있는 형식에만 나타납니다: PDF에서 워크시트당 한 페이지는 WithOnePagePerSheet; HTML에서 이미지를 인라인으로 포함하는 것은 WithExportImagesAsBase64; TSV는 formats.Get("tsv")입니다. 옵션은 포인터 의미론을 사용합니다: 생략하면 엔진 기본값이며, false를 명시적으로 전달하는 것도 동일하게 적용됩니다.
3. 출력 (sink): 파일, 바이트 또는 io.Writer
datasource.FilePathSink("output.pdf") // to disk (parent dirs are created)
&out // into memory; read it back with out.Bytes()
datasource.NewWriterSink(w) // straight into any io.Writer (http.ResponseWriter, buffer, socket)
BytesSink와 WriterSink는 “most flexible” 두 핵심 요소입니다: 이들은 변환 결과를 디스크에 저장하지 않고 바로 HTTP 응답, 객체 스토리지, zip 등으로 흐르게 합니다. 세 가지 모두 동일한 sink 매개변수의 서로 다른 구현이며, []byte 또는 io.Writer를 받는 어떤 것이든 변환기에 연결할 수 있습니다.
4. 실제 환경 예제: 하나의 Convert, 여러 도형
A. 메모리에서 변환; 다운로드 엔드포인트가 PDF를 스트리밍합니다
일반적인 서버 측 시나리오 — 사용자가 xlsx 파일을 업로드하고, 엔드포인트가 PDF를 반환하며, 임시 파일이 없습니다:
func handleExcelToPDF(w http.ResponseWriter, r *http.Request) {
var out datasource.BytesSink
if err := converter.Convert(
datasource.NewReaderSource(r.Body), // input: the request body
pdf.New(pdf.WithOnePagePerSheet(true)), // format: PDF, one page per sheet
&out, // output: memory
); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
w.Header().Set("Content-Type", "application/pdf")
w.Header().Set("Content-Disposition", `attachment; filename="report.pdf"`)
_, _ = w.Write(out.Bytes())
}
CSV / Excel / HTML을 대신 제공하려면 saveOption만 교체하십시오 (예: formats.Get("csv")); 다른 것은 변경되지 않습니다.
B. 한 번 읽고, 여러 형식으로 일괄 내보내기
입력을 한 번만 읽고, BytesSource를 통해 여러 출력에 재사용하십시오 — “모든 보고서 내보내기”에 이상적입니다:
data, err := os.ReadFile("input.xlsx")
if err != nil {
log.Fatal(err)
}
for _, ext := range []string{"pdf", "csv", "html", "json", "md"} {
var out datasource.BytesSink
if err := converter.Convert(datasource.BytesSource(data), formats.Get(ext), &out); err != nil {
log.Fatalf("%s: %v", ext, err)
}
if err := os.WriteFile("output."+ext, out.Bytes(), 0o644); err != nil {
log.Fatal(err)
}
}
C. 스프레드시트 제품군 내 “Save as” (마이그레이션 / 호환성)
스프레드시트 제품군 내에서 형식 마이그레이션, 예: xlsx → xls, xlsx → xlsb, xlsx → ods, 그리고 템플릿 xltx/xltm — 여전히 하나의 Convert이며, saveOption만 변경됩니다.
src := datasource.FilePathSource("input.xlsx")
converter.Convert(src, formats.Get("xls"), datasource.FilePathSink("legacy.xls")) // legacy Excel
converter.Convert(src, formats.Get("xlsb"), datasource.FilePathSink("binary.xlsb")) // binary Excel
converter.Convert(src, formats.Get("ods"), datasource.FilePathSink("open.ods")) // OpenDocument
converter.Convert(src, formats.Get("xltx"), datasource.FilePathSink("template.xltx")) // template
D. 형식별 옵션 조정, 필요할 때만
세밀한 제어가 필요할 때 함수형 옵션이 나타납니다 — 아래의 모든 호출은 실제이며 올바르게 타입이 지정되었습니다.
// PDF: one page per worksheet + a compliance level
pdf.New(
pdf.WithOnePagePerSheet(true),
pdf.WithCompliance("pdf15"),
pdf.WithProducer("my-report-app"),
)
// HTML: single file, images inlined as base64, CSS prefix (avoids style clashes)
html.New(
html.WithSaveAsSingleFile(true),
html.WithExportImagesAsBase64(true),
html.WithCellCssPrefix("tbl_"),
)
// CSV: custom separator and encoding
// (the separator is a byte, and the encoding is a name — matched case- and
// punctuation-insensitively, so "UTF-8", "utf8" and "UTF8" are one name)
csv.New(
csv.WithSeparator(';'),
csv.WithEncoding("UTF-8"),
)
// Image: pick the type (the only switch the image package currently exposes)
image.New(image.WithImageType("png")) // or "jpg" / "svg" / "gif" / "tif" / …
팁: CSV/HTML/이미지와 같은 단일 파일 출력의 경우, 엔진은 기본적으로 “활성"이라고 판단하는 워크시트만 내보냅니다. 범위를 제어하려면 해당 형식의 옵션을 사용하세요 — 예:
html.WithExportActiveWorksheetOnly(true)(활성 시트만?),html.WithShowAllSheets(true), 또는csv.WithExportAllSheets(true). 픽셀 수준의 이미지 품질, 정확히 어떤 시트를 렌더링할지 선택하는 기능 및 기타 심층 제어는 여전히 엔진 레이어에 존재하지만, 현재image패키지는WithImageType스위치만 노출합니다 — 더 많은 기능이 필요하면 기본 바인딩을 활용하세요; 툴킷은 시간이 지나면서 옵션을 계속 추가할 것입니다.
E. 디렉터리 전체에 대한 일괄 변환
일상적인 “convert this folder of Excels to PDF” 작업은 확장자 추론을 사용하면 매우 짧아집니다.
func convertAll(inputDir, outputDir string) error {
if err := os.MkdirAll(outputDir, 0o755); err != nil {
return err
}
return filepath.Walk(inputDir, func(path string, info os.FileInfo, err error) error {
if err != nil || info.IsDir() {
return err
}
ext := strings.ToLower(filepath.Ext(path))
if ext != ".xlsx" && ext != ".xls" && ext != ".xlsm" && ext != ".csv" {
return nil
}
out := filepath.Join(outputDir, strings.TrimSuffix(filepath.Base(path), ext)+".pdf")
if err := convert(path, out); err != nil { // reuse the convert from section 2
return fmt.Errorf("convert %s: %w", path, err)
}
fmt.Printf("done: %s -> %s\n", path, out)
return nil
})
}
F. 오류 분류
컨버터 오류는 분류 가능한 sentinel 오류이며, 정확한 처리를 위해 errors.Is와 함께 사용하세요:
err := convert("in.xlsx", "out.xyz")
switch {
case errors.Is(err, toolkiterrors.ErrUnsupportedFormat):
log.Println("this extension has no registered output format")
case errors.Is(err, os.ErrNotExist):
log.Println("the input file does not exist")
default:
log.Printf("conversion failed: %v", err)
}
formats.List()는 현재 등록된 모든 확장자를 반환합니다(정렬되고 동시성 안전) — “지원되는 형식” 목록을 생성하거나 오류 힌트를 제공할 때 유용합니다.
5. 지원되는 형식 한눈에 보기 (기본적으로 32개 등록됨)
| 제품군 | 출력 확장자 | 튜닝 패키지 |
|---|---|---|
| Excel | xlsx xlsm xltx xltm xls xlsb | saveoptions/ooxml, xls, xlsb |
| OpenDocument | ods xml dif dbf | saveoptions/ods, xml, dif, dbf |
| 텍스트 / 데이터 | csv txt tsv json sql | saveoptions/csv, txt, json, sqlScript |
| 문서 / 레이아웃 | pdf docx pptx xps pcl epub | saveoptions/pdf, docx, pptx, xps, pcl, ebook |
| 웹 | html md | saveoptions/html, markdown |
| 이미지 | png jpg jpeg gif bmp svg emf tif tiff | saveoptions/image |
바이너리를 가볍게 유지하려면 사용 중인 서브패키지만 가져오세요(예: pdf); 편의성이나 일반적인 디스패치를 위해서는 빈 임포트 …/register를 사용합니다. 서브패키지를 가져오면 해당 패키지가 등록됩니다; 레지스트리 조회는 대소문자를 구분하지 않으며, 등록되지 않은 확장자는 nil을 반환합니다(오류가 아님), 따라서 폴백 결정은 호출자에게 맡깁니다.
6. 모범 사례 및 주의 사항
하나의 진입점 — 재발명하지 마세요. 파일 간 변환은
Convert(FilePathSource, formats.Get(ext)/constructor, FilePathSink)를 사용합니다; 바이트나 스트림이 필요할 때만 sink를 교체하십시오.os.Open → ReadAll → … → os.WriteFile와 같이 직접 구현하지 마세요; source/sink가 리소스를 관리하고 상위 디렉터리를 자동으로 생성합니다.동시성 및 라이선스. 기본 엔진은 네이티브입니다: 동일 프로세스 내에서 goroutine 간에 하나의
SaveOption/workbook 객체를 공유하지 마세요; 대량 작업의 경우 파일을 순차적으로 처리하거나 프로세스를 나누어 병렬화하십시오. 평가 빌드는 로드 수를 제한합니다(프로세스당 약 백 번의NewWorkbook_Stream로드) — 대규모 벤치마크에서는 카운터를 초기화하기 위해 프로세스를 재시작하십시오.입력을 한 번만 읽고 재사용하세요. 하나의 입력으로 여러 형식을 출력하려면, 먼저
os.ReadFile로[]byte에 읽어들인 뒤BytesSource를 사용해 반복 변환하십시오. 이렇게 하면 디스크 읽기와 재로드를 반복하지 않을 수 있습니다.스트림은 버퍼링됩니다.
NewReaderSource는 첫 접근 시 버퍼링하므로 HTTP 요청 본문과 같은 일회성 입력에 적합하지만, 매우 큰 파일의 실제 스트리밍에는 적합하지 않습니다(그 경우에는 디스크를 직접 가리키는FilePathSource를 사용하세요).출력 레이아웃을 결정하는 주체를 파악하세요.
Convert는 “하나의 입력 → 하나의 출력 파일”입니다. 워크시트당 하나의 파일이나 zip이 필요하다면manipulator.Split와FolderSink/ZipSink를 사용하십시오 —Convert를 통해 강제로 처리하지 마세요.
