ตัวแปลง: หนึ่งบรรทัดที่เรียบง่ายที่สุด, ทุกสภาพแวดล้อมที่ยืดหยุ่นที่สุด

The converter package of Aspose.Cells for Go via C++ Toolkits reduces every “การแปลงสเปรดชีตเป็นรูปแบบอื่น” need to ฟังก์ชันเริ่มต้นเดียว:

converter.Convert(source, saveOption, sink) error

มันมีเพียงสามพารามิเตอร์เท่านั้น และแต่ละพารามิเตอร์ตอบคำถามได้อย่างแม่นยำหนึ่งคำถาม:

พารามิเตอร์ชนิดคำถามที่ตอบค่าตัวอย่างทั่วไป
sourcedatasource.DataSourceข้อมูลเข้าเข้ามาจากที่ไหน?FilePathSource(path), BytesSource(data), NewReaderSource(r)
saveOptionsaveoptions.SaveOptionผลลัพธ์เป็นอะไรและปรับแต่งอย่างไร?formats.Get("pdf") for defaults by name, or pdf.New(pdf.WithOnePagePerSheet(true)) for fine control
sinkdatasource.DataSinkผลลัพธ์จะไปที่ไหน?FilePathSink(path), &BytesSink{}, NewWriterSink(w)

สำหรับสไตล์ ที่กระชับที่สุด, ให้ใช้ค่าเริ่มต้นในทุกแกนทั้งสาม; สำหรับ ที่ยืดหยุ่นที่สุด, ปรับแต่ละตัวควบคุมแยกกัน. เนื่องจากแกนทั้งสามเป็นอิสระกัน, ฟังก์ชัน Convert เดียวกันจึงเหมาะกับสภาพแวดล้อมไฟล์, หน่วยความจำ, HTTP และ batch อย่างเป็นธรรมชาติ. (ยังมีคำสั่งแบบบรรทัดเดียวแบบเก่า 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)
	}
}

ล้าสมัย. ConvertSpreadsheetToFile เป็น wrapper ที่บางเบาซึ่งถูกเก็บไว้เพื่อความเข้ากันได้ย้อนหลัง; โค้ดใหม่จะถูกส่งต่อไปยัง 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)
	}
}

ตัวควบคุมทั้งสามใช้ค่าเริ่มต้น: input = ไฟล์, format = pdf.New() โดยไม่มีการกำหนดค่า, output = ไฟล์. นั่นคือรูปแบบ “ที่กระชับที่สุด” — ไม่มีการเรียก os.Open/os.Create ด้วยตนเอง, ไม่มีการจัดสรรอ็อบเจกต์, ไม่มีการปิด handle; source/sink จะจัดการทรัพยากรให้คุณ.

1.3 เปรียบเทียบรูปแบบไฟล์→ไฟล์สองแบบ

ConvertSpreadsheetToFile(in, out)converter.Convert(source, opt, sink)
อินพุตเฉพาะเส้นทางไฟล์ใดก็ได้ DataSource: path, []byte, หรือ reader
เอาต์พุตเฉพาะเส้นทางไฟล์ใดก็ได้ DataSink: path, bytes, หรือ io.Writer
รูปแบบเอาต์พุตสรุปจากส่วนขยายโดยอัตโนมัติ, ใช้ค่าเริ่มต้นเท่านั้นใดก็ได้ saveOption: ค่าเริ่มต้นหรือการปรับแต่งเฉพาะรูปแบบ
การนำเข้าเพิ่มเติมต้องการให้ลงทะเบียนรูปแบบ (_ "…/register", หรือ subpackage saveoptions/* ที่ตรงกัน)ไม่มี, เมื่อคุณส่งคอนสตรัคเตอร์เช่น pdf.New()
สถานะตัวห่อบางแบบที่เลิกใช้แล้ว (เสถียร, คงไว้เพื่อความเข้ากันได้)จุดเข้าตรงเดียวที่ระบุในเอกสารสำหรับโค้ดใหม่

ไฟล์เดียวกัน → ผลลัพธ์ไฟล์, สองสถานการณ์ที่แตกต่างกัน:

  • ConvertSpreadsheetToFile — คุณมีเส้นทางสองเส้นโดยตรงและพอใจกับการตั้งค่าเริ่มต้นของเอนจินสำหรับรูปแบบเป้าหมาย. เหมาะสำหรับสคริปต์การแปลงแบบครั้งเดียว, ชุดการย้ายข้อมูล, และตัวช่วยทดสอบ. ข้อเสีย: อินพุต, เอาต์พุต, และการตั้งค่าไม่สามารถออกจากรูปแบบ “file path + defaults” ได้ — และมันถูกยกเลิกการใช้งานแล้ว.
  • 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" นี้?

มีสองวิธีในการรับ saveOption; นี่คือแนวคิดเดียวที่สไตล์ “most concise” ต้องเข้าใจ:

  • ค้นหาจากรีจิสทรีโดยใช้ชื่อฟอร์แมต (formats.Get): ส่วนขยายต้องมีอยู่ในรีจิสทรี formats ทุก saveoptions/* subpackage จะลงทะเบียนตัวเองใน init() ของมันเอง แต่เฉพาะเมื่อถูกนำเข้าเท่านั้น ให้นำเข้า subpackage ที่คุณต้องการทีละอัน (เช่นเฉพาะ pdf หากคุณแปลงเป็น PDF) หรือ blank-import …/register ครั้งเดียว, ซึ่งจะลงทะเบียนฟอร์แมตทั้งหมด 32 รูปแบบพร้อมกัน — “universal converter” ด้านบนพึ่งพาบรรทัดเดียวนี้
  • เรียกคอนสตรัคเตอร์โดยตรง (pdf.New(), markdown.New()): ข้ามรีจิสทรี ไม่ต้องนำเข้า register; ค่าใช้จ่ายคือบรรทัดการนำเข้าหนึ่งบรรทัดต่อฟอร์แมตที่คุณใช้

โดยสรุป: ให้ใช้ _ "…/register" เท่านั้นเมื่อคุณแก้ไขผ่าน formats.Get + ส่วนขยายของผลลัพธ์; การส่งคอนสตรัคเตอร์โดยตรงไม่ต้องการอะไรเพิ่มเติม การนำเข้าแบบว่างเปล่านั้นไม่มีอันตรายและมักปรากฏในตัวอย่างอย่างเป็นทางการเสมอ

3. ที่ยืดหยุ่นที่สุด: ปรับแต่ละปุ่มแยกกัน

เมื่อความต้องการเกินกว่า “file to file with default settings” คุณไม่ต้องเปลี่ยน API — พารามิเตอร์ Convert สามตัวสามารถสลับกันได้อย่างอิสระ.

1. อินพุต (source): จากไฟล์, ไปยังหน่วยความจำ, ไปยังสตรีมใดก็ได้

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): ค่าเริ่มต้น หรือ ปรับแต่ง

สถานการณ์รูปแบบการเขียนทำไม
รูปแบบบางอย่างด้วยการตั้งค่าเริ่มต้นformats.Get("pdf")ค้นหาตามส่วนขยาย; ไม่แยกแยะตัวพิมพ์ใหญ่/เล็ก; nil หากไม่ได้ลงทะเบียน
รูปแบบที่มีตัวเลือกเฉพาะรูปแบบpdf.New(pdf.WithOnePagePerSheet(true))ตัวเลือกเชิงฟังก์ชัน
การตั้งค่าเริ่มต้น, รูปแบบที่ระบุชัดเจนooxml.New() / csv.New() / …คอนสตรัคเตอร์ศูนย์อาร์กิวเมนต์หนึ่งตัวต่อรูปแบบ
รูปแบบส่วนตัวที่กำหนดเองformats.Register("fmt", factory)เชื่อมต่อกับรีจิสทรี — ดู docs/register.md

ตัวเลือกแบบฟังก์ชันปรากฏเฉพาะในรูปแบบที่มีตัวเลือกเหล่านั้น: หน้าหนึ่งต่อแผ่นงานใน PDF คือ WithOnePagePerSheet; รูปภาพแบบฝังใน HTML คือ WithExportImagesAsBase64; TSV คือ formats.Get("tsv"). ตัวเลือกเป็นแบบ pointer-semantic: ไม่ระบุ = ค่าเริ่มต้นของเอนจิน; การส่งค่า 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 คือกุญแจสองประการที่ทำให้ “ที่ยืดหยุ่นที่สุด”: พวกมันทำให้ผลลัพธ์การแปลงข้ามการเขียนลงดิสก์โดยสมบูรณ์และไหลตรงเข้าสู่การตอบสนอง HTTP, ที่เก็บวัตถุ, ไฟล์ zip, และอื่น ๆ ทั้งสามเป็นการดำเนินการที่แตกต่างกันของพารามิเตอร์ sink เดียวกัน, ดังนั้นสิ่งใดก็ตามที่รับ []byte หรือ io.Writer สามารถเชื่อมต่อกับตัวแปลงได้.


4. ตัวอย่างในสภาพแวดล้อมจริง: หนึ่ง Convert หลายรูปทรง

A. แปลงในหน่วยความจำ; endpoint การดาวน์โหลดสตรีม PDF

สถานการณ์ทั่วไปบนเซิร์ฟเวอร์ — ผู้ใช้อัปโหลดไฟล์ xlsx, endpoint จะส่งกลับเป็น 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. “บันทึกเป็น” ภายในตระกูลสเปรดชีต (การย้าย / ความเข้ากันได้)

การย้ายรูปแบบภายในตระกูลสเปรดชีต เช่น 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/image, เอนจินจะส่งออกเฉพาะ worksheet ที่มันพิจารณาว่าเป็น “active” โดยค่าเริ่มต้น หากต้องการควบคุมขอบเขต ให้ใช้ตัวเลือกของรูปแบบเอง — เช่น html.WithExportActiveWorksheetOnly(true) (only the active sheet?), 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() คืนค่าทุกส่วนขยายที่ลงทะเบียนอยู่ในปัจจุบัน (เรียงลำดับ, ปลอดภัยต่อการทำงานพร้อมกัน) — มีประโยชน์สำหรับการสร้างรายการ “supported formats” หรือเป็นคำแนะนำข้อผิดพลาด


5. รูปแบบที่รองรับในภาพรวม (32 รูปแบบที่ลงทะเบียนโดยค่าเริ่มต้น)

กลุ่มส่วนขยายผลลัพธ์แพคเกจการปรับแต่ง
Excelxlsx xlsm xltx xltm xls xlsbsaveoptions/ooxml, xls, xlsb
OpenDocumentods xml dif dbfsaveoptions/ods, xml, dif, dbf
ข้อความ / ข้อมูลcsv txt tsv json sqlsaveoptions/csv, txt, json, sqlScript
เอกสาร / เค้าโครงpdf docx pptx xps pcl epubsaveoptions/pdf, docx, pptx, xps, pcl, ebook
เว็บhtml mdsaveoptions/html, markdown
รูปภาพpng jpg jpeg gif bmp svg emf tif tiffsaveoptions/image

เพื่อให้ไบนารีมีขนาดเล็กลง ให้ import เฉพาะ subpackage ที่คุณใช้ (เช่น pdf); เพื่อความสะดวกหรือการส่งต่อทั่วไป ให้ทำการ blank‑import …/register. การ import subpackage จะทำให้มันลงทะเบียน; การค้นหาใน registry ไม่สนใจตัวพิมพ์ใหญ่‑เล็ก; ส่วนขยายที่ไม่ได้ลงทะเบียนจะคืนค่า nil (ไม่ใช่ข้อผิดพลาด) ทำให้การตัดสินใจ fallback ถูกมอบให้กับผู้เรียกใช้.

6. แนวทางปฏิบัติที่ดีที่สุดและข้อควรระวัง

  1. จุดเข้าหนึ่งเดียว — อย่าประดิษฐ์ใหม่ File-to-file ใช้ Convert(FilePathSource, formats.Get(ext)/constructor, FilePathSink); เปลี่ยน sink เท่านั้นเมื่อคุณต้องการไบต์หรือสตรีม อย่าทำเอง os.Open → ReadAll → … → os.WriteFile; source/sink จะจัดการทรัพยากรและสร้างไดเรกทอรีแม่ให้คุณ.

  2. การทำงานพร้อมกันและการให้สิทธิ์ เครื่องยนต์พื้นฐานเป็นเนทีฟ: ไม่ ควรแชร์อ็อบเจกต์ SaveOption/workbook ตัวเดียวระหว่าง goroutine ในกระบวนการเดียว; สำหรับงานจำนวนมากให้ประมวลผลไฟล์แบบต่อเนื่องหรือทำแบบขนานผ่านหลายกระบวนการ การสร้างรุ่นประเมินจะจำกัดจำนวนการโหลด (ประมาณหนึ่งร้อยการโหลด NewWorkbook_Stream ต่อกระบวนการ) — สำหรับการทดสอบขนาดใหญ่ให้รีสตาร์ทกระบวนการเพื่อรีเซ็ตตัวนับ.

  3. อ่านอินพุตครั้งเดียวแล้วใช้ซ้ำ เพื่อสร้างหลายรูปแบบจากอินพุตเดียว, ใช้ os.ReadFile เพื่ออ่านเป็น []byte ก่อนและแปลงซ้ำด้วย BytesSource เพื่อหลีกเลี่ยงการอ่านดิสก์และโหลดซ้ำหลายครั้ง.

  4. สตรีมจะถูกบัฟเฟอร์ NewReaderSource จะบัฟเฟอร์ในครั้งแรกที่เข้าถึง, ดังนั้นเหมาะกับอินพุตแบบครั้งเดียวเช่น body ของ HTTP request, ไม่ใช่การสตรีมจริงของไฟล์ขนาดใหญ่มาก (ใช้ FilePathSource ชี้ตรงไปที่ดิสก์สำหรับกรณีนั้น).

  5. รู้ว่าใครเป็นผู้กำหนดรูปแบบผลลัพธ์ Convert คือ “หนึ่งอินพุต → หนึ่งไฟล์ผลลัพธ์”. หากคุณต้องการ ไฟล์หนึ่งต่อเวิร์กชีต หรือ zip, ให้ใช้ manipulator.Split พร้อม FolderSink/ZipSink — อย่าบังคับให้ผ่าน Convert.