Konverter: eine Zeile in ihrer einfachsten Form, jede Umgebung in ihrer flexibelsten Form
Das converter-Paket von Aspose.Cells for Go via C++ Toolkits reduziert jede Anforderung, ein Tabellenblatt in ein anderes Format zu konvertieren, auf eine Einstiegfunktion:
converter.Convert(source, saveOption, sink) error
Es hat nur drei Parameter, und jeder beantwortet genau eine Frage:
| Parameter | Typ | Frage, die sie beantwortet | Typische Werte |
|---|---|---|---|
source | datasource.DataSource | Woher kommt die Eingabe? | FilePathSource(path), BytesSource(data), NewReaderSource(r) |
saveOption | saveoptions.SaveOption | Als was ausgeben, wie eingestellt? | formats.Get("pdf") für Standardwerte per Name, oder pdf.New(pdf.WithOnePagePerSheet(true)) für feine Steuerung |
sink | datasource.DataSink | Wohin geht die Ausgabe? | FilePathSink(path), &BytesSink{}, NewWriterSink(w) |
Für den kompaktesten Stil nehmen Sie die Standardeinstellungen auf allen drei Achsen; für den flexibelsten Stil drehen Sie jeden Regler unabhängig. Da die drei Achsen unabhängig sind, passt das gleiche Convert natürlich in Datei-, Speicher-, HTTP- und Batch-Umgebungen. (Es gibt auch einen Legacy‑Einzeiler, ConvertSpreadsheetToFile, für den einfachen Datei→Datei‑Fall — verglichen in Abschnitt 1 unten.) Der Rest dieses Artikels bewegt sich vom kompaktesten zum flexibelsten Ansatz und erweitert bei jedem Schritt das vorherige Snippet, anstatt zu einer anderen API zu wechseln.
1. Der einfachste: ein Aufruf für ein Format
1.1 Ein eingebauter Datei→Datei-Einzeiler: ConvertSpreadsheetToFile
Das Paket liefert auch einen älteren, noch kürzeren Eintrag für den klassischen “diese Datei in jene Datei konvertieren”-Fall. Alles, was man braucht, sind zwei Pfade:
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)
}
}
Veraltet.
ConvertSpreadsheetToFileist ein dünner Wrapper, der aus Gründen der Rückwärtskompatibilität beibehalten wird; neuer Code wird unten zuconverter.Convertgeleitet. Für den Datei→Datei‑Fall sind die beiden exakt gleichwertig — das ist alles, wasConvertSpreadsheetToFiletut:
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 und das oben genannte Convert‑Formular erzeugen identische Ergebnisse; was sich unterscheidet, ist das Szenario, wie im Folgenden verglichen wird.
1.2 Der empfohlene Einzeiler: Convert mit Standardeinstellungen
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)
}
}
Alle drei Regler übernehmen ihre Standardwerte: Eingabe = eine Datei, Format = pdf.New() ohne Konfiguration, Ausgabe = eine Datei. Das ist die “kompakteste” Form — kein manuelles os.Open/os.Create, keine Objektallokation, kein Schließen von Handles; die source/sink verwalten Ressourcen für Sie.
1.3 Die beiden Datei→Datei-Formen im Vergleich
ConvertSpreadsheetToFile(in, out) | converter.Convert(source, opt, sink) | |
|---|---|---|
| Eingabe | nur ein Dateipfad | beliebige DataSource: Pfad, []byte, oder Reader |
| Ausgabe | nur ein Dateipfad | beliebige DataSink: Pfad, Bytes, oder io.Writer |
| Ausgabeformat | immer aus der Erweiterung abgeleitet, nur Standardwerte | beliebige saveOption: Standard oder formatabhängige Feinabstimmung |
| Extra-Import | erfordert die Registrierung des Formats (_ "…/register", oder das passende saveoptions/* Unterpaket) | keine, wenn Sie einen Konstruktor wie pdf.New() |
| Status | veralteter dünner Wrapper (stabil, aus Kompatibilitätsgründen behalten) | der dokumentierte einzelne Einstiegspunkt für neuen Code |
Gleiche Datei→Dateiergebnis, zwei verschiedene Szenarien:
ConvertSpreadsheetToFile— Sie haben buchstäblich zwei Pfade und sind mit den Standardeinstellungen der Engine für das Zielformat zufrieden. Ideal für einmalige Konvertierungsskripte, Migrationsbatches und Testhilfen. Der Preis: Eingabe, Ausgabe und Einstellungen können nie die Form „Dateipfad + Vorgaben“ verlassen — und es ist veraltet.converter.Convert— Sie möchten denselben Einzeiler, aber eines der drei Argumente soll austauschbar bleiben: morgen ist die Eingabe ein[]byte‑Upload, das Ziel benötigtpdf.WithOnePagePerSheet(true), oder die Ausgabe soll direkt in eine HTTP‑Antwort gehen. Das sind genau die Szenarien aus Abschnitt 3 und 4 — schreiben Sie es einmal mitConvertund jede Änderung ist eine ein‑Argument‑Bearbeitung.
2. Das einfachste × N: eine Funktion für alle 32 Formate
Die nächste Stufe der Prägnanz besteht darin, die gleiche Funktion zu verwenden, egal welches Format Sie anvisieren. Da saveOption aus der Dateierweiterung der Ausgabedatei berechnet werden kann, führt das Herausziehen dieser Ableitung zu einem “universellen Dateikonverter”:
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")
}
Die Verwendung bleibt identisch — nur die Ausgabedateierweiterung ändert sich:
$ 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
Was ist dieser leere _ "…/register" Import?
Es gibt zwei Wege, ein saveOption zu erhalten; dies ist das einzige Konzept, das der “most concise”-Stil verstehen muss:
- Im Register nach dem Formatnamen suchen (
formats.Get): Die Erweiterung muss imformats‑Register vorhanden sein. Jedersaveoptions/*‑Unterpaket registriert sich selbst in seiner eigeneninit(), jedoch nur beim Import. Importieren Sie die Unterpakete, die Sie benötigen, einzeln (z. B. nurpdf, wenn Sie nach PDF konvertieren), oder blank‑importieren Sie…/registereinmal, wodurch alle 32 Formate auf einmal registriert werden – der oben erwähnte „universelle Konverter“ beruht auf dieser einzigen Zeile. - Einen Konstruktor direkt aufrufen (
pdf.New(),markdown.New()): Umgeht das Register, keinregister‑Import nötig; der Preis ist eine Import‑Zeile pro verwendetem Format.
Kurz gesagt: Verwenden Sie nur _ "…/register" wenn Sie über formats.Get + die Ausgabenerweiterung auflösen; das direkte Übergeben eines Konstruktors erfordert nichts Weiteres. Der leere Import ist harmlos und ist in den offiziellen Beispielen immer vorhanden.
3. Am flexibelsten: jeden Regler einzeln drehen
Wenn der Bedarf über “Datei zu Datei mit Standardeinstellungen” hinausgeht, ändern Sie die API nicht — die drei Convert‑Parameter können unabhängig voneinander ausgetauscht werden.
1. Eingabe (Quelle): von einer Datei, in den Speicher, zu jedem Stream
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, …)
Hinweis: Die zugrunde liegende Engine benötigt zufälligen Zugriff auf den gesamten Inhalt, sodass
ReaderSourceden Stream beim ersten Zugriff vollständig puffert; jeder spätereOpenliefert eine Kopie dieses Puffers. Verwenden Sie ihn bedenkenlos für HTTP, wissen Sie jedoch, dass es kein echtes “Konvertieren beim Streamen” ist.
2. Format (saveOption): Standardwerte oder angepasst
| Szenario | Schreibstil | Warum |
|---|---|---|
| Ein Format mit Standardeinstellungen | formats.Get("pdf") | nach Erweiterung gesucht; nicht groß-/kleinschreibungssensitiv; nil wenn nicht registriert |
| Ein Format mit format-spezifischen Optionen | pdf.New(pdf.WithOnePagePerSheet(true)) | funktionale Optionen |
| Standardeinstellungen, explizites Format | ooxml.New() / csv.New() / … | ein null-Argument‑Konstruktor pro Format |
| Ein benutzerdefiniertes privates Format | formats.Register("fmt", factory) | in das Register einbinden — siehe docs/register.md |
Funktionale Optionen erscheinen nur bei den Formaten, die sie unterstützen: Eine Seite pro Arbeitsblatt im PDF ist WithOnePagePerSheet; Bilder inline im HTML sind WithExportImagesAsBase64; TSV ist formats.Get("tsv"). Optionen haben Zeigersemantik: Weglassen = der Standard der Engine; das explizite Übergeben von false zählt ebenfalls.
3. Ausgabe (sink): eine Datei, Bytes oder ein 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 und WriterSink sind die beiden Schlüssel zu „am flexibelsten“: Sie ermöglichen es, dass das Konvertierungsergebnis das Laufwerk vollständig überspringt und direkt in eine HTTP‑Antwort, Objektspeicher, ein Zip usw. fließt. Alle drei sind verschiedene Implementierungen desselben sink‑Parameters, sodass alles, was []byte oder einen io.Writer akzeptiert, in den Konverter eingesteckt werden kann.
4. Real-Umgebungsbeispiele: ein Convert, viele Formen
A. In-Memory konvertieren; der Download-Endpunkt streamt PDF
Das gängige serverseitige Szenario — ein Benutzer lädt xlsx hoch, der Endpunkt gibt PDF zurück, keine temporären Dateien:
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())
}
Um stattdessen CSV / Excel / HTML auszugeben, tauschen Sie nur die saveOption aus (zum Beispiel formats.Get("csv")); sonst ändert sich nichts.
B. Einmal lesen, Batch-Export in viele Formate
Lese die Eingabe nur einmal ein und verwende sie anschließend über BytesSource für beliebig viele Ausgaben – ideal für das Exportieren jedes Berichts:
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. “Speichern unter” innerhalb der Tabellenkalkulationsfamilie (Migration / Kompatibilität)
Formatmigration innerhalb der Tabellenkalkulationsfamilie, z. B. xlsx → xls, xlsx → xlsb, xlsx → ods, und die Vorlagen xltx/xltm — immer noch ein Convert, nur die saveOption ändert sich:
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. Optionen pro Format anpassen, nur wenn nötig
Funktionale Optionen erscheinen, wenn Sie feine Kontrolle benötigen — beachten Sie, dass jeder Aufruf unten real und korrekt typisiert ist:
// 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" / …
Hinweis: Für Einzelausgaben wie CSV/HTML/Image exportiert die Engine standardmäßig nur das Arbeitsblatt, das sie als „aktiv“ betrachtet. Um den Umfang zu steuern, verwenden Sie die jeweiligen Optionen des Formats – z. B.
html.WithExportActiveWorksheetOnly(true)(nur das aktive Blatt?),html.WithShowAllSheets(true)odercsv.WithExportAllSheets(true). Pixelgenaue Bildqualität, die genaue Auswahl der zu rendernden Arbeitsblätter und weitere tiefgreifende Steuerungen existieren weiterhin auf Engine‑Ebene, aber das aktuelleimage‑Paket stellt nur den SchalterWithImageTypebereit – greifen Sie bei Bedarf auf das zugrunde liegende Binding zurück; das Toolkit wird im Laufe der Zeit weitere Optionen integrieren.
E. Batch-Konvertierung über ein Verzeichnis
Der alltägliche “diesen Ordner mit Excels in PDF konvertieren”-Job wird mit der Erweiterungsableitung sehr kurz.
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. Klassifizierung von Fehlern
Konverterfehler sind klassifizierbare Sentinel‑Fehler; kombinieren Sie sie mit errors.Is für eine präzise Handhabung:
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() gibt jede aktuell registrierte Erweiterung zurück (sortiert, nebenläufig sicher) — praktisch zum Erzeugen einer „unterstützten Formate“-Liste oder eines Fehlertipps.
5. Unterstützte Formate auf einen Blick (32 standardmäßig registriert)
| Familie | Ausgabe‑Erweiterungen | Tuning‑Paket |
|---|---|---|
| Excel | xlsx xlsm xltx xltm xls xlsb | saveoptions/ooxml, xls, xlsb |
| OpenDocument | ods xml dif dbf | saveoptions/ods, xml, dif, dbf |
| Text / Daten | csv txt tsv json sql | saveoptions/csv, txt, json, sqlScript |
| Dokumente / Layout | pdf docx pptx xps pcl epub | saveoptions/pdf, docx, pptx, xps, pcl, ebook |
| Web | html md | saveoptions/html, markdown |
| Bilder | png jpg jpeg gif bmp svg emf tif tiff | saveoptions/image |
Um das Binary schlank zu halten, importieren Sie nur die Subpakete, die Sie verwenden (wie pdf); für Komfort oder generische Weiterleitung, blank-import …/register. Das Importieren eines Subpakets löst dessen Registrierung aus; Registrierungs‑Lookups sind case‑insensitive; eine nicht registrierte Erweiterung gibt nil zurück (kein Fehler), sodass die Entscheidung über das Fallback dem Aufrufer überlassen wird.
6. Best Practices und Fallstricke
Ein einziger Einstiegspunkt — nicht neu erfinden. File-to-File verwendet
Convert(FilePathSource, formats.Get(ext)/constructor, FilePathSink); wechseln Sie die Sinks nur, wenn Sie Bytes oder einen Stream benötigen. Rollen Sie nicht selbstos.Open → ReadAll → … → os.WriteFilezusammen; die Quelle/der Sink verwalten Ressourcen und erstellen für Sie die übergeordneten Verzeichnisse.Parallelität und Lizenzierung. Die zugrunde liegende Engine ist nativ: teilen Sie nicht ein
SaveOption/Workbook‑Objekt über Goroutinen im selben Prozess; für Massenverarbeitung Dateien sequenziell verarbeiten oder über Prozesse parallelisieren. Die Evaluierungs‑Build begrenzt die Ladevorgänge (etwa einhundertNewWorkbook_Stream‑Ladevorgänge pro Prozess) — bei großen Benchmarks den Prozess neu starten, um den Zähler zurückzusetzen.Lesen Sie die Eingabe einmal und verwenden Sie sie dann erneut. Um mehrere Formate aus einer Eingabe zu erzeugen,
os.ReadFileSie sie zuerst in ein[]byteund konvertieren Sie wiederholt mitBytesSource, um wiederholte Festplattenlesungen und Neuladevorgänge zu vermeiden.Streams werden gepuffert.
NewReaderSourcepuffert beim ersten Zugriff, daher eignet es sich für einmalige Eingaben wie einen HTTP‑Request‑Body, nicht für echtes Streaming sehr großer Dateien (verwenden SieFilePathSource, das direkt auf die Festplatte zeigt, für solche Fälle).Wissen Sie, wer das Ausgabe‑Layout bestimmt.
Convertist „eine Eingabe → eine Ausgabedatei“. Wenn Sie eine Datei pro Arbeitsblatt oder ein ZIP benötigen, verwenden Siemanipulator.Splitmit einemFolderSink/ZipSink— zwingen Sie es nicht überConvert.
