Passa al contenuto principale

Ripeti i paragrafi - Guida al ciclo Foreach

I documenti spesso contengono strutture di contenuto ripetitive, come elenchi di elementi, record multipli o sezioni ripetute con una formattazione simile. PDF4meIl motore di template di offre potenti funzionalità di iterazione per generare dinamicamente più paragrafi e sezioni a partire da raccolte di dati.


Comprensione dei cicli Foreach

IL foreach Il ciclo è il meccanismo principale per scorrere le raccolte di dati e generare contenuti ripetuti. Ogni iterazione elabora un elemento della raccolta e genera l'output corrispondente.

Sintassi base del ciclo foreach

<<foreach [item in collection]>>
Content with <<[item.property]>>
<</foreach>>

Componenti:

  • item - Variabile che rappresenta l'elemento corrente nell'iterazione
  • collection - L'array o la raccolta di dati da iterare
  • Blocco di contenuto: il contenuto del modello viene ripetuto per ogni elemento

Ripetizione dei paragrafi

Genera più paragrafi scorrendo una raccolta di dati e creando testo formattato per ciascun elemento.

Esempio: Valutazioni delle applicazioni

Sintassi del modello:

<<foreach [app in applications]>><<[app.listAppName]>> in <<[app.listAppType]>> platform is a <<[app.category]>> app and has a <<[app.AppRating]>> rating.
<</foreach>>

Fonte dati (JSON):

{
"surveyName": "Top-rated Apps",
"applications": [
{
"listAppName": "Instagram",
"listAppType": "iOS",
"category": "Social Media",
"AppRating": "4.9"
},
{
"listAppName": "Whatsapp",
"listAppType": "iOS",
"category": "Chat",
"AppRating": "4.8"
},
{
"listAppName": "Player UG",
"listAppType": "Android",
"category": "Gaming",
"AppRating": "4.75"
}
]
}

Output generato:

Instagram in iOS platform is a Social Media app and has a 4.9 rating.
Whatsapp in iOS platform is a Chat app and has a 4.8 rating.
Player UG in Android platform is a Gaming app and has a 4.75 rating.

Gestione dei contenitori vuoti

Quando una collezione potrebbe essere vuota, usa il Any() Metodo per verificare la presenza di dati prima di iterare. Questo previene eccezioni di tipo null e consente di visualizzare contenuti alternativi.

Controllo nullo di base

Modello con controllo Any():

<<if [applications.Any()]>>
<<foreach [app in applications]>><<[app.listAppName]>> in <<[app.listAppType]>> platform is a <<[app.category]>> app and has a <<[app.AppRating]>> rating.
<</foreach>>
<<else>>No applications listed
<</if>>

Questo approccio:

  1. Verifica se la collezione contiene elementi
  2. Esegue un ciclo sugli elementi, se disponibili.
  3. Visualizza un messaggio di fallback se la raccolta è vuota

Cicli foreach annidati

Crea strutture gerarchiche annidando i cicli foreach uno dentro l'altro. Questo è utile per visualizzare le relazioni padre-figlio o le strutture dati multilivello.

Esempio: reparto e dipendenti

Modello:

<<foreach [dept in departments]>>
Department: <<[dept.name]>>
<<foreach [emp in dept.employees]>>
- <<[emp.name]>> (<<[emp.position]>>)
<</foreach>>
<</foreach>>

Dati:

{
"departments": [
{
"name": "Engineering",
"employees": [
{ "name": "John Smith", "position": "Senior Developer" },
{ "name": "Jane Doe", "position": "Tech Lead" }
]
},
{
"name": "Marketing",
"employees": [
{ "name": "Mike Johnson", "position": "Marketing Manager" }
]
}
]
}

Ripetizione di sezioni complesse

I cicli foreach possono ripetere intere sezioni di contenuto, inclusi più paragrafi, formattazione e strutture annidate.

Ripetizione di più paragrafi

Modello:

<<foreach [product in products]>>
Product Name: <<[product.name]>>
Description: <<[product.description]>>
Price: $<<[product.price]>>
Available: <<[product.inStock]>>

<</foreach>>

Questo modello genera un blocco di descrizione completo per ogni prodotto, mantenendo tutta la formattazione e le interruzioni di paragrafo.


Iterazione condizionale

Combina i cicli foreach con le istruzioni condizionali per la generazione selettiva dei contenuti.

Esempio: Visualizzazione condizionale

Modello:

<<foreach [employee in employees]>>
<<if [employee.age > 50]>>
Senior Employee: <<[employee.name]>> - Age: <<[employee.age]>>
<</if>>
<</foreach>>

In alternativa, utilizzare metodi di enumerazione:

Modello:

<<foreach [employee in employees.Where(e => e.age > 50)]>>
Senior Employee: <<[employee.name]>> - Age: <<[employee.age]>>
<</foreach>>

Formattazione all'interno dei cicli

Applica la formattazione ai campi all'interno dei cicli foreach per ottenere uno stile di output coerente.

Modello:

<<foreach [customer in customers]>>
Customer: <<[customer.name]:caps>>
Last Visit: <<[customer.lastVisit]:"MMMM dd, yyyy">>
Status: <<[customer.status]:upper>>

<</foreach>>

Variabili di ciclo e indicizzazione

È possibile accedere alle informazioni sulla posizione del ciclo utilizzando variabili implicite (se supportate dalla versione del motore di template in uso).

Variabili di ciclo comuni

  • Indice dell'elemento corrente (basato su 0 o su 1 a seconda dell'implementazione)
  • Conteggio delle iterazioni del ciclo
  • Indicatori del primo/ultimo elemento

Esempio di utilizzo (se supportato):

<<foreach [item in items]>>
<<[$index + 1]>>. <<[item.name]>>
<</foreach>>

Considerazioni sulle prestazioni

Migliori pratiche per i cicli

  1. Limitare la dimensione della collezione - Filtrare le raccolte di grandi dimensioni prima dell'elaborazione del modello
  2. Evitare nidi profondi - Limitare i cicli annidati a 2-3 livelli per prestazioni migliori
  3. Pre-elaborazione dei dati - Eseguire calcoli complessi prima di passare i dati ai modelli
  4. Utilizzare query efficienti - Filtrare e ordinare i dati a livello di origine dati

Esempio: Dati prefiltrati

Invece di:

<<foreach [emp in employees.Where(e => e.age > 30).OrderBy(e => e.name)]>>

Pre-filtra i dati nella tua applicazione e trasmetti i dati filtrati:

<<foreach [emp in filteredEmployees]>>

Modelli comuni

Schema 1: Elenco numerato

<<foreach [item in items]>>
<<[$index]>>. <<[item.title]>>
<</foreach>>

Modello 2: Contenuto raggruppato

<<foreach [category in categories]>>
## <<[category.name]>>

<<foreach [item in category.items]>>
- <<[item.name]>>
<</foreach>>
<</foreach>>
<<foreach [report in reports]>>
Report: <<[report.title]>>
Total Records: <<[report.records.Count()]>>
Average Value: <<[report.records.Average(r => r.value)]>>
<</foreach>>

Risoluzione dei problemi

Problemi comuni

Problema: Errori di riferimento nullo Soluzione: Utilizzo Any() per controllare le collezioni prima dell'iterazione

Problema: Interruzioni di riga o spaziature indesiderate Soluzione: Gestisci con attenzione gli spazi bianchi nel tuo modello

Problema: Problemi di prestazioni con collezioni di grandi dimensioni Soluzione: Prefiltrare i dati e limitare le dimensioni delle raccolte

Problema: Collegamento dati errato Soluzione: Verifica che i nomi delle proprietà corrispondano esattamente alla struttura dei dati.


Esempio pratico: voci di fattura

Modello completo:

Invoice #<<[invoiceNumber]>>
Date: <<[invoiceDate]:"dd.MM.yyyy">>

Items:
<<if [lineItems.Any()]>>
<<foreach [item in lineItems]>>
<<[item.name]:caps>> - Qty: <<[item.quantity]>> - Price: $<<[item.price]:"F2">> - Total: $<<[item.quantity * item.price]:"F2">>
<</foreach>>

Subtotal: $<<[lineItems.Sum(i => i.quantity * i.price)]:"F2">>
<<else>>
No items in this invoice.
<</if>>

:::Suggerimento per iterazioni complesse Per scenari di iterazione complessi, si consiglia di pre-elaborare i dati nella logica dell'applicazione prima di passarli al template. Questo migliora la leggibilità e le prestazioni del template.

:::