Questa pagina può contenere testo tradotto automaticamente.

Generatore di PDF .NET

Con l'aiuto di Docotic.Pdf, puoi generare documenti PDF componendoli a partire da elementi strutturali come pagine, contenitori, segmenti di testo, immagini, collegamenti, intestazioni, piè di pagina, tabelle, elenchi e altro. Questi elementi sono disponibili tramite la Layout API di livello superiore, fornita dal componente aggiuntivo Layout gratuito per Docotic.Pdf. L'API supporta anche componenti personalizzati riutilizzabili.

Illustrazione di come Docotic.Pdf genera PDF: disponi elementi come immagini, tabelle e testo e la libreria produce un PDF da quel layout

La Layout API consente di definire i documenti interamente in codice C# o VB.NET usando un approccio fluente. In base a questa descrizione, il generatore PDF fornito dal componente aggiuntivo può produrre documenti con layout arbitrariamente complessi, da pagine semplici a report PDF altamente strutturati.

Nozioni di base sulla generazione PDF

Per generare documenti PDF usando la Layout API, è necessario il componente aggiuntivo Layout gratuito. Per usare la libreria core e i componenti aggiuntivi è inoltre richiesta una chiave di licenza. Puoi usare una chiave di prova gratuita oppure una chiave acquistata.

Installare il componente aggiuntivo

Il modo consigliato è installare il componente aggiuntivo da NuGet.

Install-Package BitMiracle.Docotic.Pdf.Layout

Il gestore pacchetti si occuperà automaticamente delle dipendenze.

Se preferisci installare manualmente il componente aggiuntivo, inizia scaricando l'archivio ZIP con i binari di Docotic.Pdf. Estrai l'archivio e aggiungi i riferimenti alle seguenti DLL:

  • BitMiracle.Docotic.Pdf.dll
  • BitMiracle.Docotic.Pdf.Layout.dll dalla sottocartella Layout add-on.

Ottenere una chiave di licenza

Per provare la libreria, richiedi una chiave di licenza gratuita con durata limitata compilando il modulo nella pagina di download di Docotic.Pdf. Se hai già acquistato una licenza, usa il codice fornito dopo l'acquisto.

Il componente aggiuntivo Layout è gratuito e non richiede una licenza aggiuntiva. Puoi usare la Layout API con la licenza Docotic.Pdf che possiedi già.

Ciao, mondo! con la Layout API

Ecco un esempio di codice che usa l'API per generare un PDF con la classica frase "Hello, world!":

BitMiracle.Docotic.LicenseManager.AddLicenseData("PUT-LICENSE-HERE");

PdfDocumentBuilder.Create().Generate("hello.pdf", doc => doc.Pages(pages =>
{
    pages.Content().Text("Hello, world!");
}));

Questo codice produce un PDF di una sola pagina con il testo nell'angolo in alto a sinistra.

Comprendere l'esempio di codice

L'esempio inizia aggiungendo una chiave di licenza. Senza una licenza, la libreria Docotic.Pdf non genera nulla. Il codice che produce il PDF inizia alla riga successiva.

Il codice crea un'istanza del generatore di documenti chiamando il metodo statico PdfDocumentBuilder.Create(). La chiamata al metodo Generate avvia il processo di generazione del PDF. Questo metodo accetta due parametri: il nome del file da produrre e un delegato di tipo Action<Document>. Il componente aggiuntivo genera hello.pdf come risultato della chiamata Generate.

Per sapere quale layout deve avere il PDF, il generatore di documenti chiama il delegato con un'istanza Document. Il codice del delegato compone il contenuto del documento. In questo esempio, il delegato usa il metodo Pages per fornire al generatore un altro delegato che definisce il layout delle pagine del documento.

Il generatore chiama il delegato passato al metodo Pages con un'istanza PageLayout. Questa istanza rappresenta una o più pagine nel documento. Il numero esatto di pagine dipende dal contenuto aggiunto a esse.

Il delegato della pagina chiama il metodo Content per accedere al contenitore di layout del contenuto principale della pagina o delle pagine. Una chiamata concatenata al metodo Text del contenitore aggiunge il segmento di testo di esempio alla pagina. Consulta la guida sui contenitori di layout per una spiegazione dettagliata del loro funzionamento.

Il generatore di documenti divide automaticamente il contenuto tra le pagine, creando esattamente il numero di pagine necessario per contenere tutti i dati aggiunti al contenitore di layout del contenuto principale. In questo esempio, è sufficiente una sola pagina, quindi l'output contiene esattamente una pagina.

Attività comuni oltre l'esempio di base

Il codice di esempio crea prima un'istanza PdfDocumentBuilder e poi chiama il metodo Generate per produrre un PDF. Puoi configurare il generatore prima che inizi a generare il PDF.

Ad esempio, puoi produrre un PDF crittografato fornendo al generatore un gestore di crittografia. Puoi anche specificare metadati da includere nel documento generato. Per maggiori dettagli su come personalizzare il generatore, consulta l'articolo separato.

Il codice di esempio usa solo il contenitore di layout dello slot di contenuto principale, ma sono disponibili anche altri slot di contenuto. Ecco l'elenco completo dei metodi PageLayout per accedere agli slot di contenuto:

  • Background() - restituisce il livello di sfondo, coperto dagli altri contenuti.
  • Header() - restituisce l'intestazione comune a tutte le pagine.
  • Content() - restituisce lo slot del contenuto principale della pagina.
  • Footer() - restituisce il piè di pagina comune a tutte le pagine.
  • Foreground() - restituisce il livello in primo piano, visualizzato sopra gli altri contenuti.

Solo il contenuto nello slot principale influisce sul numero di pagine nel PDF generato. Il generatore di documenti ripete tutti gli slot diversi da quello fornito da Content() in ogni pagina. Per maggiori informazioni sugli slot di contenuto, vedi l'articolo sul layout di pagina.

Molti documenti usano layout diversi su pagine diverse. Ad esempio, la prima pagina può avere un design in stile copertina, mentre le pagine successive usano un layout più semplice. Alcuni documenti includono pagine speciali per le tabelle oppure applicano sfondi diversi a seconda della sezione. Per generare documenti di questo tipo con Docotic.Pdf e il componente aggiuntivo Layout, chiama più volte il metodo Document.Pages. Puoi trovare un esempio funzionante nel nostro repository di esempi.

Organizzare il codice

Per codice breve, come nell'esempio, va bene concatenare le chiamate e usare lambda annidate. Quando costruisci qualcosa di più grande, può essere più comodo suddividere il codice in metodi separati. Questo rende il codice più facile da leggere e mantenere.

Ecco come appare l'esempio Hello, world! quando il suo codice è suddiviso in metodi.

public void GeneratePdf()
{
    BitMiracle.Docotic.LicenseManager.AddLicenseData("PUT-LICENSE-HERE");

    PdfDocumentBuilder.Create().Generate("hello.pdf", BuildDocument);
}

private void BuildDocument(Document doc)
{
    doc.Pages(BuildPages);
}

private void BuildPages(PageLayout pages)
{
    pages.Content().Text("Hello, world!");
}

Perché generare PDF con la Layout API di Docotic.Pdf

La Layout API è un modo moderno e adatto agli sviluppatori per generare PDF da blocchi componibili senza dover comprendere i dettagli interni del formato PDF. Dispone il PDF con prestazioni elevate e con un comportamento deterministico e prevedibile. Puoi usare l'API in scenari di generazione documenti ad alto volume.

L'API è disponibile quando si usa Docotic.Pdf insieme al componente aggiuntivo Layout gratuito. Sia Docotic.Pdf sia il componente aggiuntivo Layout sono DLL con codice gestito al 100%, senza blocchi di codice unsafe. La Layout API è implementata senza dipendenze esterne di terze parti, come un browser o binari Skia, risultando in una soluzione leggera, con overhead ridotto e facile da distribuire e mantenere.

Panoramica dell'API

La Layout API è un'API fluente e piacevole da usare. Descrivi interamente in codice il layout del documento usando elementi di layout flessibili, e il generatore distribuisce il contenuto, lo impagina automaticamente e renderizza il risultato come PDF.

Il componente aggiuntivo Layout usa un sistema di layout dichiarativo e basato sul flusso. I suoi elementi di layout includono elenchi, colonne, righe, tabelle, immagini, segmenti di testo, intestazioni e piè di pagina, contenitori e altro. Invece di posizionare manualmente gli elementi a coordinate esatte, descrivi il comportamento desiderato degli elementi. Il generatore di documenti calcola quindi il layout finale e crea il PDF.

Il sistema di layout basato sul flusso garantisce che il layout si adatti alle dimensioni della pagina e al contenuto. Grazie a questo sistema, il componente aggiuntivo eccelle in layout complessi, strutturati e basati su regole. Puoi annidare diversi tipi di contenitori e costruire strutture sofisticate senza sacrificare la leggibilità.

Quando lavori con la Layout API, puoi concatenare insieme la maggior parte delle chiamate. Questo porta a un codice più compatto ed espressivo rispetto alle API tradizionali. L'ordine delle chiamate in una catena è importante. Tutto è fortemente tipizzato, offrendo sicurezza a tempo di compilazione e rendendo il codice più adatto al refactoring. Puoi anche eseguire test unitari sul codice che usa la Layout API.

Per rendere l'implementazione del layout ancora più concisa, puoi estendere l'API con metodi tuoi e costruirci attorno un DSL pulito ed espressivo.

Per maggiori informazioni su posizionamento e creazione di DSL, consulta l'articolo che spiega come controllare dimensioni, posizione, allineamento e comportamento di rendering dei contenitori.

Versioni .NET e supporto della piattaforma

Puoi usare la Layout API in progetti destinati a .NET Standard 2.1 e framework più recenti. In altre parole, il componente aggiuntivo Layout è compatibile con .NET 5 fino a .NET 10. Inoltre, è supportato .NET Core 3.0+.

Puoi generare PDF con la Layout API in ASP.NET Core, app MAUI, Unity, Xamarin e applicazioni console. Docotic.Pdf con il componente aggiuntivo Layout può produrre PDF su Windows, macOS e Linux.

Piattaforme cloud e immagini Docker

Docotic.Pdf con il componente aggiuntivo Layout può essere eseguito in ambienti cloud Azure e AWS, incluse configurazioni serverless. La libreria e il componente aggiuntivo supportano completamente variazioni dinamiche dell'hardware, autoscaling e altre funzionalità runtime cloud-native.

Nella maggior parte degli scenari cloud è richiesta una licenza non vincolata. La FAQ sulla licenza spiega come scegliere la licenza appropriata per le applicazioni cloud.

La Layout API funziona senza problemi nei container Docker. Non è necessaria alcuna configurazione speciale per generare PDF quando si eseguono la libreria e il componente aggiuntivo Layout all'interno di un container.

Aggiungere testo ai file PDF

Il testo è una parte fondamentale di qualsiasi documento PDF. Puoi usare i metodi Text della classe LayoutContainer per aggiungere testo a uno slot di contenuto.

Illustrazione di pagine di un documento circondate da esempi di stili di testo come Titolo, Didascalia, Normale, Collegamento, Grassetto e Nota a piè di pagina

Segmenti di testo

Nell'esempio Hello, world, ho usato il sovraccarico LayoutContainer.Text(string) per aggiungere testo al contenuto principale della pagina. Vediamo ora un altro sovraccarico del metodo Text.

public static void GenerateTextPdf()
{
    PdfDocumentBuilder.Create().Generate("text-spans.pdf", doc => doc.Pages(pages =>
    {
        pages.Content().Text(AddTextSpans);
    }));
}

private static void AddTextSpans(TextContainer text)
{
    text.Line("About VB.NET")
        .Style(t => t.Strong);

    text.Span("VB.NET is a multi-paradigm, object-oriented language ");
    text.Span("that runs on .NET, Mono, and the ");
    text.Hyperlink(
        ".NET Framework",
        new Uri("https://dotnet.microsoft.com/download/dotnet-framework"));
    text.Line(".");

    text.Span("Released by Microsoft in 2002, ");
    text.Line("it continues the lineage of the original Visual Basic language.");
}

Questo codice usa i metodi Span e Line della classe TextContainer per aggiungere testo alla riga corrente. Il metodo Line inoltre completa la riga corrente. Il codice di esempio usa anche il metodo Hyperlink per associare un collegamento a una risorsa esterna a uno specifico segmento di testo.

Nota come il codice di esempio applichi una formattazione in grassetto alla prima riga usando il metodo Style. Esploriamo più nel dettaglio il concetto di stili di testo.

Stili di testo

Gli stili di testo consentono di personalizzare l'aspetto del testo. La classe TextStyle fornisce metodi per modificare la dimensione del carattere, la spaziatura tra lettere, i colori e altre proprietà del testo. Gli oggetti TextStyle sono immutabili, quindi ogni chiamata a un metodo produce una nuova istanza di stile. Puoi applicare gli stili di testo a diversi livelli del layout.

PdfDocumentBuilder.Create().Generate("text-styles.pdf", doc =>
{
    doc.Pages(pages =>
    {
        pages.TextStyle(TextStyle.Parent.FontSize(30));

        pages.Content()
            .TextStyle(TextStyle.Parent.FontColor(new PdfRgbColor(0, 0, 255)))
            .Text(text =>
            {
                text.Span("Hello,");

                text.Span("World!")
                    .Style(TextStyle.Parent.Underline());
            });
    });
});

La proprietà TextStyle.Parent restituisce uno stile speciale in cui tutte le proprietà del testo non sono definite. Nell'esempio sopra, il codice disegna “Hello, World!” in blu, con la seconda parola sottolineata, usando una dimensione del font di 30 punti.

Questo accade perché il codice:

  • imposta la dimensione del font a 30 punti a livello di pagina,
  • poi imposta il colore del testo su blu per lo slot di contenuto principale,
  • poi applica lo stile di sottolineatura all'ultimo segmento di testo.

Ogni stile successivo eredita i precedenti tramite la proprietà TextStyle.Parent.

Usando i metodi della classe TextStyle, puoi, tra le altre cose, cambiare la direzione del testo da destra a sinistra. Consulta un altro esempio di uso dell'ereditarietà degli stili di testo nel nostro repository di esempi.

Tipografia

La classe TextStyle supporta la personalizzazione di tutte le proprietà del testo tranne il font associato. Per cambiare il font predefinito, usa i metodi Document.TextStyleWithFont per creare uno stile di testo basato su un font specifico. Puoi usare un font installato nel sistema operativo oppure caricarne uno da un file o da uno stream.

Dopo aver creato uno stile basato su un font, puoi applicare ulteriori proprietà opzionali e poi usare lo stile risultante su un segmento di testo. Questo esempio C# mostra come usare un font di sistema.

PdfDocumentBuilder.Create().Generate("text-style-with-font.pdf", doc =>
{
    var font = SystemFont.Family("Calibri");
    var style = doc.TextStyleWithFont(font).FontSize(30);

    doc.Pages(pages =>
    {
        pages.Content().Text(text =>
        {
            text.Span("Hello,");

            text.Span("World!")
                .Style(style);
        });
    });
});

Il metodo TextStyleWithFont include un parametro opzionale che specifica come il font deve essere incorporato nel documento generato. Per impostazione predefinita, la libreria:

  • incorpora i glifi utilizzati per i font TrueType/OpenType,
  • incorpora tutti i glifi per i font Type1 e CFF,
  • non incorpora i glifi per i font PDF incorporati (font Base14).

Grazie a queste impostazioni predefinite, i documenti che usano font TrueType e OpenType possono rimanere di dimensioni ridotte anche quando vengono usati font grandi. Puoi anche specificare un loader di font personalizzato, font di fallback e un gestore per i glifi mancanti. Consulta il codice di esempio nel nostro repository di esempi per i dettagli su come gestire i font nei documenti PDF.

La Layout API fornisce una raccolta di stili predefiniti, che puoi accedere e modificare tramite la classe Typography.

PdfDocumentBuilder.Create().Generate("typography.pdf", doc =>
{
    doc.Typography(t =>
    {
        var fontsPath = Environment.GetFolderPath(Environment.SpecialFolder.Fonts);
        var arialFont = new FileInfo(Path.Combine(fontsPath, "arial.ttf"));

        t.Document = doc.TextStyleWithFont(arialFont);
        t.Header = t.Parent.FontSize(20).FontColor(new PdfGrayColor(20));
        t.Footer = t.Footnote;
    });

    doc.Pages(pages =>
    {
        pages.Header().AlignCenter().Text("Header");

        pages.Content().Text(t =>
        {
            t.Line("Title").Style(t => t.Title);
            t.Line("Heading 1").Style(t => t.Heading1);
            t.Line("Regular");
        });

        pages.Footer()
            .Height(20)
            .AlignCenter()
            .Text(t => t.CurrentPageNumber());
    });
});

Consiglio di sostituire gli stili predefiniti configurando la tipografia per l'intero documento, anche se non è obbligatorio e puoi comunque applicare gli stili di testo a livello di singolo segmento.

Con la classe Typography, non è necessario memorizzare i riferimenti agli stili di testo in variabili. Invece, registri gli stili richiesti usando i metodi Document.Typography e in seguito vi accedi tramite le proprietà dell'oggetto Typography. Consulta l'esempio Typography per vedere come usare stili di testo predefiniti e personalizzati quando si generano documenti PDF.

Molti documenti PDF reali, come report o fatture, includono intestazioni e piè di pagina. Questa sezione mostra come aggiungerli entrambi a un PDF.

public static void GeneratePdfWithHeaderAndFooter()
{
    PdfDocumentBuilder.Create()
        .Generate("header-footer.pdf", doc => doc.Pages(pages =>
    {
        pages.Size(PdfPaperSize.A6).Margin(10);

        BuildPagesHeader(pages.Header());
        BuildPagesFooter(pages.Footer());

        pages.Content().Text("Hello, world!");
    }));
}

public static void BuildPagesHeader(LayoutContainer header)
{
    header.TextStyle(TextStyle.Parent.FontSize(8))
        .AlignRight()
        .Text(t =>
        {
            t.Line($"Created by: {Environment.UserName}");
            t.Line($"Date: {DateTime.Now}");
        });
}

public static void BuildPagesFooter(LayoutContainer footer)
{
    footer.AlignRight().Text(text =>
    {
        text.Style(t => t.Parent.FontColor(new PdfRgbColor(255, 0, 0)));

        text.CurrentPageNumber();
        text.Span(" / ");
        text.PageCount();
    });
}

Il metodo BuildPagesHeader imposta una dimensione del font più piccola per il testo dell'intestazione. Usa due righe per il contenuto dell'intestazione: una con il nome dell'utente corrente e un'altra con la data corrente. Il testo è allineato a destra.

Nota che il codice non specifica alcuna dimensione esplicita per l'intestazione. Occupa l'intera larghezza della pagina meno i margini sinistro e destro, e la sua altezza dipende dall'altezza delle righe di testo.

Il metodo BuildPagesFooter mostra come inserire il numero di pagina corrente nel piè di pagina del PDF. La libreria calcola automaticamente il numero di pagina corrente e il conteggio totale delle pagine. Puoi accedere a questi valori usando i metodi CurrentPageNumber e PageCount di un oggetto TextContainer.

La Layout API offre anche un modo per formattare i numeri di pagina. Ad esempio, puoi disegnare numeri di pagina esadecimali in questo modo:

text.CurrentPageNumber().Format(p => "0x" + p?.ToString("x2"));

Il nostro repository di esempi contiene un altro esempio di aggiunta di un'intestazione e un piè di pagina a un PDF. In quell'esempio i numeri di pagina sono formattati come numeri romani.

Inserire immagini

Come dice il proverbio, un'immagine vale più di molte parole. Nelle citazioni o nelle ricevute, spesso includerai il logo della tua azienda o un'altra immagine importante. Per questo esempio, ne userò una semplice e gradevole.

Per usare un'immagine, devi prima aggiungerla al documento. La libreria può caricare immagini da un file o da uno stream. Sono supportati solo i formati raster: PNG, JPEG, JPEG 2000, BMP, GIF e TIFF.

Una volta ottenuto un oggetto Image, puoi impostarlo come contenuto di uno o più contenitori di layout chiamando il metodo Image del contenitore. Puoi ridimensionare, ruotare, aggiungere padding e disporre l'immagine esattamente come qualsiasi altro contenuto.

PdfDocumentBuilder.Create().Generate("image-with-text.pdf", doc =>
{
    var imageFile = new FileInfo("red-flowers-at-butterfly-world.jpg");
    var image = doc.Image(imageFile);

    doc.Pages(pages =>
    {
        pages.Size(PdfPaperSize.A6);
        pages.Content().Column(c =>
        {
            c.Spacing(20);

            c.Item()
                .AlignCenter()
                .Text("Hello, world!")
                .FontSize(20);

            c.Item()
                .AlignCenter()
                .MaxWidth(200)
                .Image(image);
        });
    });
});

Il codice di esempio usa sia testo sia un'immagine nello slot di contenuto principale. Tuttavia, un contenitore di layout può contenere solo testo oppure solo un'immagine. Per includere entrambi nello slot di contenuto principale della pagina, serve un contenitore composto.

Uso un contenitore Column per disporre il testo e l'immagine verticalmente, uno dopo l'altro. Il metodo Item del contenitore Column fornisce un sottocontenitore. Una chiamata a Item crea un contenitore per il testo, e un'altra crea un contenitore per l'immagine. Il contenitore composto con tutti i suoi sottocontenitori diventa il contenuto principale.

Per eseguire il codice di esempio, scarica l'immagine del fiore dal nostro repository di esempi e inseriscila nella directory di lavoro della tua app.

Immagini online

Se hai solo un URL dell'immagine invece di un file, scarica l'immagine in uno stream di memoria e crea un oggetto Image da quello stream. L'esempio seguente mostra come usare immagini online con la Layout API.

public static async Task AddImageWithTextFromUrl()
{
    using var http = new HttpClient();
    using var stream = await http.GetStreamAsync("url/to/image");

    var memoryStream = new MemoryStream();
    await stream.CopyToAsync(memoryStream);
    memoryStream.Position = 0;

    PdfDocumentBuilder.Create().Generate("online-image-with-text.pdf", doc =>
    {
        var image = doc.Image(memoryStream);

        doc.Pages(pages =>
        {
            pages.Size(PdfPaperSize.A6);
            pages.Content().Column(c =>
            {
                c.Spacing(20);

                c.Item()
                    .AlignCenter()
                    .Text("Hello, world!")
                    .FontSize(20);

                c.Item()
                    .AlignCenter()
                    .MaxWidth(200)
                    .Image(image);
            });
        });
    });
}

Poiché il metodo esegue lavoro asincrono (scaricando un'immagine da un URL), è dichiarato come async Task invece di void. I chiamanti devono usare await per garantire che la generazione del PDF venga completata correttamente. Nel tuo codice, un metodo simile può anche restituire un valore; in quel caso sarebbe dichiarato come async Task<TResult>.

Creare elenchi

Che cos'è un elenco? Puoi pensarlo come un gruppo di elementi numerati scritti uno sotto l'altro. La Layout API non fornisce un tipo speciale di contenitore per gli elenchi, ma è facile implementarne uno usando altri contenitori composti.

var dayNames = DateTimeFormatInfo.InvariantInfo.DayNames;
var dayNamesSpain = DateTimeFormatInfo.GetInstance(new CultureInfo("es-ES")).DayNames;

PdfDocumentBuilder.Create().Generate("list.pdf", doc => doc.Pages(pages =>
{
    pages.Size(PdfPaperSize.A6);
    pages.Content().Column(column =>
    {
        for (int i = 0; i < dayNames.Length; i++)
        {
            column.Item().Row(row =>
            {
                row.Spacing(5);
                row.AutoItem().Text($"{i + 1}.");
                row.RelativeItem().Text(t =>
                {
                    t.Line(dayNames[i]);
                    t.Line($"In Spain they call it {dayNamesSpain[i]}");
                });
            });
        }
    });
}));

Il codice di esempio crea l'elenco come colonna di righe. Ogni riga contiene due elementi: il primo (a sinistra) contiene il numero dell'elemento e il secondo (a destra) contiene il testo dell'elemento. Il codice imposta esplicitamente lo spazio tra gli elementi di ogni riga.

Per disporre gli elementi, il contenitore Row deve avere la dimensione di ciascun elemento specificata esplicitamente oppure calcolarla. In questo esempio vengono usati i metodi AutoItem e RelativeItem. Di conseguenza, il contenitore della riga calcola la larghezza necessaria per il primo elemento e usa poi la larghezza disponibile residua per il secondo elemento.

Usando questo approccio e regolando l'aspetto delle righe secondo necessità, puoi creare un elenco che si adatta meglio al layout e allo stile del tuo documento.

Creare tabelle

Molti documenti PDF contengono tabelle, il che non sorprende perché le tabelle migliorano la chiarezza e l'organizzazione dei dati. Questa sezione mostra come creare una tabella in un PDF usando la Layout API.

public static void AddTable()
{
    PdfDocumentBuilder.Create().Generate("table.pdf", doc => doc.Pages(pages =>
    {
        pages.Size(PdfPaperSize.A6);

        var color = new PdfGrayColor(75);
        pages.Content().Padding(20).Table(t =>
        {
            t.Columns(c =>
            {
                c.RelativeColumn(4);
                c.RelativeColumn(1);
                c.RelativeColumn(4);
            });

            t.Header(h =>
            {
                h.Cell().Background(color).Text("Month");
                h.Cell().Background(color).Text("Days");
                h.Cell().Background(color).Text("First Day");
            });

            var year = DateTime.Now.Year;
            for (int yearDiff = 0; yearDiff < 4; yearDiff++)
            {
                for (int i = 11; i >= 0; i--)
                {
                    var stats = GetMonthStats(year - yearDiff, i);

                    t.Cell().Text(stats.Item1);
                    t.Cell().Text(stats.Item2);
                    t.Cell().Text(stats.Item3);
                }
            }
        });
    }));
}

private static (string, string, string) GetMonthStats(int year, int monthIndex)
{
    return (
        $"{DateTimeFormatInfo.InvariantInfo.MonthNames[monthIndex]} {year}",
        DateTime.DaysInMonth(year, monthIndex + 1).ToString(),
        new DateTime(year, monthIndex + 1, 1).DayOfWeek.ToString()
    );
}

Il codice di esempio crea una tabella semplice che mostra informazioni di base sui mesi dell'anno corrente e dei tre anni precedenti. Il codice definisce tre colonne con larghezze relative. Le colonne più a sinistra e più a destra sono larghe quattro volte la colonna centrale.

Il codice definisce anche l'intestazione della tabella aggiungendo celle di intestazione e specificando il testo e il colore di sfondo per ciascuna cella. Quando una tabella non entra in una singola pagina, l'intestazione viene ripetuta in ogni pagina occupata dalla tabella. Puoi osservare questo comportamento nel PDF generato dal codice di esempio.

Per costruire le righe vengono usati due semplici cicli. Il ciclo esterno itera sugli anni e quello interno itera sui mesi in ordine inverso. Il ciclo interno recupera le informazioni relative a ciascun mese e poi aggiunge tre celle per formare una riga.

Per maggiori dettagli, puoi leggere l'articolo che spiega in profondità le funzionalità del contenitore Table.

I documenti PDF supportano collegamenti interni che consentono ai lettori di passare a un'altra posizione nello stesso file. In un visualizzatore PDF, questi collegamenti appaiono come elementi di testo o immagine cliccabili. Funzionano come hyperlink, ma invece di puntare a un sito esterno navigano all'interno del documento stesso.

Illustrazione dei collegamenti interni in un PDF, che mostra sezioni del documento collegate con icone di collegamento e destinazione

Molti documenti PDF usano collegamenti interni per i segnalibri o per un indice, aiutando i lettori a spostarsi rapidamente tra le sezioni. Ecco come puoi aggiungere un collegamento a una sezione del documento usando la Layout API:

PdfDocumentBuilder.Create().Generate("link.pdf", doc =>
{
    doc.Pages(pages =>
    {
        pages.Content().Column(c =>
        {
            const string SectionName = "Chapter 1";
            c.Item().SectionLink(SectionName).Text("Link");

            c.Item().PageBreak();

            c.Item().Section(SectionName).Text("Target");
        });
    });
});

Il codice di esempio rende il testo della prima pagina un collegamento alla sezione con il nome specificato. Lo fa chiamando il metodo SectionLink sul contenitore di layout che contiene il testo. In questo punto la sezione può esistere oppure no. Il testo diventa cliccabile in un visualizzatore PDF.

Il codice poi marca il testo nella seconda pagina come inizio della sezione con lo stesso nome. Il suo aspetto e comportamento non cambiano, ma diventa la destinazione del collegamento nella prima pagina. Questo viene fatto chiamando il metodo Section sul corrispondente contenitore di layout.

In questo esempio, sia il collegamento sia la sua destinazione sono segmenti di testo, ma puoi creare sezioni e collegamenti su qualsiasi contenitore di layout. Può trattarsi di un contenitore con un'immagine, di un contenitore tabella o di un contenitore costruito da te.

Vedi un esempio di come creare un indice PDF nel nostro repository di esempi.

Progettare layout PDF complessi

La Layout API fornisce una varietà di contenitori di layout che puoi combinare per produrre documenti PDF arbitrariamente complessi. Puoi anche estendere l'API con componenti personalizzati tuoi.

Gli esempi in questa pagina sono intenzionalmente semplici, progettati per creare documenti lineari così puoi concentrarti sulle idee principali senza perderti nei dettagli. Se vuoi vedere come diversi contenitori possano essere combinati per generare un PDF più complesso, dai un'occhiata al corrispondente esempio nel nostro repository di esempi su GitHub.

Oltre a usare i contenitori incorporati, puoi definire e usare componenti di layout personalizzati. Questi componenti sono particolarmente utili quando vuoi che una singola classe incapsuli sia i dati sia la logica di layout. Tenere tutto in un unico posto rende il componente più facile da comprendere, modificare e riutilizzare, offrendo al tempo stesso un modo flessibile per gestire layout complessi.

Per creare un componente di layout personalizzato, implementa nella tua classe l'interfaccia ILayoutComponent. Durante la generazione di un PDF, la libreria chiama il metodo Compose dell'interfaccia e fornisce un oggetto LayoutContext. Il tuo codice può usare questo oggetto per creare elementi di layout e accedere alle informazioni sul documento in fase di generazione.

Per aggiungere un componente di layout personalizzato al tuo layout, chiama il metodo Component della classe LayoutContainer. In termini di dimensionamento e posizionamento, un componente personalizzato si comporta esattamente come testo o immagini.

Per un esempio di implementazione di un componente personalizzato con l'interfaccia ILayoutComponent, vedi l'esempio Componenti di layout.

Altri modi per creare PDF

Docotic.Pdf offre diversi modi per creare PDF, ciascuno adatto a scenari diversi. Questa sezione spiega quando fare affidamento sulla Layout API e quando altri approcci possono essere più adatti.

Quando preferire la Layout API

La Layout API di Docotic.Pdf è un modo potente per generare PDF da layout strutturati. Consente di costruire documenti componendo testo, immagini, contenitori e tabelle in strutture annidate arbitrariamente complesse. Il processo di generazione è veloce, usa una quantità ragionevole di memoria e si comporta in modo prevedibile.

Docotic.Pdf e il componente aggiuntivo Layout formano un set leggero e completamente autonomo. L'API non richiede librerie esterne né browser per generare PDF. Questo la rende una scelta solida per microservizi .NET, applicazioni cloud, specialmente serverless, e altri ambienti in cui le dimensioni del footprint contano.

Poiché il layout del documento è definito in codice, puoi eseguire test unitari su qualsiasi sua parte. La logica di layout può essere riutilizzata come qualsiasi altro codice e puoi incapsulare sia i dati sia il comportamento di layout in componenti personalizzati.

Alternative alla Layout API

Un articolo dedicato fornisce un confronto dettagliato di tutti i modi per creare PDF con Docotic.Pdf. Di seguito sono riportate alcune delle alternative più usate.

  • Conversione da HTML a PDF
    Riutilizza template HTML/CSS esistenti. Scegli l'approccio HTML-to-PDF quando il tuo team produce già documenti in HTML/CSS e hai bisogno di versioni PDF di quei documenti.

  • Generazione PDF a basso livello
    Fornisce il massimo controllo disponibile nella libreria sulla struttura e sul contenuto del PDF. Scegli questo approccio quando hai bisogno di posizionamento a livello di pixel o grafica vettoriale complessa. È consigliato per scenari critici per le prestazioni o quando è richiesto il footprint più ridotto possibile.

  • Generazione PDF basata su template
    Offre un modo veloce e prevedibile per compilare documenti senza progettare o disporre i loro elementi. Scegli questo approccio quando hai una struttura PDF predefinita, come template approvati o soggetti a controlli di conformità, e devi solo modificare campi di testo, sostituire segnaposto, allegare documenti correlati ed eseguire attività simili.

  • Unione e composizione di PDF
    Consente di creare un PDF a partire da elementi esistenti invece di costruirlo da zero. Scegli questo approccio quando hai immagini, pagine scansionate o altri PDF da combinare in un unico file.

Confronto con altre soluzioni di generazione PDF

Questa sezione contiene due tabelle di confronto: una con i punti chiave e un'altra con informazioni dettagliate e strutturate su come Docotic.Pdf con il componente aggiuntivo Layout si confronta con altre soluzioni popolari per la generazione di PDF.

Punti chiave del confronto

Esistono opzioni valide per generare PDF, incluse quelle gratuite. Tuttavia, funzionalità come firma, crittografia o unione dei documenti variano, il che può limitare gli strumenti che si adattano davvero alle tue esigenze.

Soluzione Quando usarlo Ideale per
Docotic.Pdf con il componente aggiuntivo Layout Quando vuoi un motore di layout di alta qualità e ad alte prestazioni, capace di produrre PDF ottimizzati, con supporto avanzato per firme, crittografia e modifica dei PDF su più piattaforme Generazione di alta qualità di fatture, report, estratti conto e documenti simili, con un'ottima esperienza per gli sviluppatori. Ideale quando ti serve un'elaborazione PDF di livello enterprise e supporto professionale
PDFsharp + MigraDoc Quando vuoi una libreria gratuita con licenza MIT per la generazione PDF di base e non hai bisogno di firme digitali o algoritmi di crittografia moderni Creazione di documenti semplici in progetti open source o con budget limitato
QuestPDF Quando vuoi un motore di layout moderno dedicato esclusivamente alla generazione PDF e non ti servono modifica, firme o crittografia Generazione PDF di alta qualità con licenza MIT o commerciale a basso costo, a condizione che tutte le funzionalità non legate alla generazione siano gestite altrove
iText Quando hai bisogno di un toolkit PDF maturo e ricco di funzionalità sia per generare sia per elaborare PDF, e sei disposto a rendere open source la tua soluzione sotto licenza AGPL/GPLv3 oppure ad acquistare una costosa licenza commerciale Team già familiari con l'API iText e quindi non penalizzati dalla sua ripida curva di apprendimento

Confronto dettagliato

Esamina la tabella per comprendere il contesto più ampio e trarre le tue conclusioni.

  Docotic.Pdf con Layout PDFsharp + MigraDoc QuestPDF iText
Funzionalità PDF Libreria PDF completa Generazione PDF e modifica limitata Solo generazione PDF Funzionalità PDF estese
Modello di rendering Motore di layout moderno, dichiarativo e retained-mode Motore di layout basato su box Motore di layout moderno, dichiarativo e retained-mode Motore di layout basato su box + albero di rendering
Tipo di API API fluente API imperativa API fluente API imperativa
Esperienza per sviluppatori Eccellente. L'API è pulita, moderna e intuitiva Buona. La progettazione dell'API è convenzionale Eccellente. L'API è pulita, moderna e intuitiva Soddisfacente. L'API è prolissa ed eccessivamente complessa
Subsetting dei font Supportato; per impostazione predefinita vengono incorporati solo i glifi usati Non supportato; può produrre PDF inutilmente grandi Supportato; per impostazione predefinita vengono incorporati solo i glifi usati Supportato; per impostazione predefinita vengono incorporati solo i glifi usati
Direzione del contenuto da destra a sinistra (RTL) Supportata Non supportata Supportata Supportata
Firme digitali Supportate, incluse LTV e firme esterne Non supportate Non supportate Supportate, incluse LTV e firme esterne
Crittografia / autorizzazioni Completamente supportata Solo crittografia RC4, senza supporto per AES o certificati Non supportata Completamente supportata
Dipendenze esterne Nessuna Nessuna Componenti basati su SkiaSharp / Skia Nessuna
Supporto Supporto professionale per prospect e clienti; supporto prioritario con licenze di fascia alta Supporto della community; supporto professionale acquistabile separatamente Supporto della community tramite GitHub Supporto della community per la versione AGPL; supporto professionale per i titolari di licenza commerciale
Licenza Commerciale, con licenze gratuite per casi d'uso idonei MIT MIT per privati e piccole aziende; licenza commerciale richiesta per aziende più grandi AGPL per uso open source, costosa licenza commerciale per progetti proprietari
Licenze per sviluppatori Sviluppatori illimitati con tutte le licenze Sviluppatori illimitati con tutte le licenze Sviluppatori illimitati con MIT; 10 sviluppatori con Professional; sviluppatori illimitati con Enterprise Sviluppatori illimitati con la versione AGPL; licenze per sviluppatore con la licenza commerciale

Conclusione

Docotic.Pdf con il componente aggiuntivo Layout offre un modo moderno, ad alte prestazioni e di alta qualità per generare PDF in C# e VB.NET. La libreria produce report, estratti conto, fatture e documenti simili. La sua API fluente, ben progettata, offre un'eccellente esperienza per gli sviluppatori. Puoi fare affidamento sul supporto professionale fornito da Bit Miracle per Docotic.Pdf e i suoi componenti aggiuntivi.

A differenza di alcune altre soluzioni per la generazione PDF, Docotic.Pdf è una API PDF completa di funzionalità. La libreria può firmare PDF generati con firme digitali, incluse firme con supporto LTV. Docotic.Pdf è in grado di usare certificati archiviati su hardware sicuro come token USB e smart card. Sono supportati anche gli Hardware Security Module (HSM) basati su cloud, come Microsoft Azure Key Vault e AWS Key Management Service (KMS).

Con Docotic.Pdf, puoi allegare documenti di supporto come fogli di calcolo o note vocali ai PDF generati. Per visualizzare documenti in una pagina web o in un'interfaccia simile, puoi creare immagini miniature da una o più delle loro pagine.

Passi successivi: