2016-05-27 10 views
0

Für ein Projekt, an dem ich gerade arbeite, untersuche ich Methoden, die unser Team normalerweise nicht zum Generieren von Dokumenten verwendet. Normalerweise verwenden wir ActiveReports, um ein PDF zu generieren, das wir dem Client bereitstellen, aber das ist aufgrund unserer Papiergröße keine Option - wir haben schwere Probleme bekommen alles, was nicht 8,5 "x 11" zu spielen ist gut mit Browser-seitige PDF-Plugins oder die Drucker, die wir unterstützen.Mehrseitiges Dokument in Open XML aus Datenliste generieren

Die spezifische Sache, die ich versuche, ist, ein Dokument mit 1 ... n 4 "x6" Karteikarten zu erstellen. Wie bereits erwähnt, kann ich eine variable Anzahl von Dateneinträgen haben, die ich generieren muss.

Der einzige Weg, ich Open XML in der Vergangenheit verwendet habe, ist eine Vorlage zu nehmen, ersetzen Keywords mit Daten, die ich dann dazu dienen, das resultierende Dokument bis zu den Kunden, wie weiter unten injizieren wollte:

Bericht Klasse:

public class ThingReport : IDisposable 
{ 
    #region Variables/Properties 

    private readonly string _templatePath = string.Empty; 
    private MemoryStream _reportStream; 

    #endregion Variables/Properties 

    #region Constructor 

    public ThingReport(string templatePath) 
    { 
     _templatePath = templatePath; 
    } 

    #endregion Constructor 

    #region Methods 

    public void Dispose() 
    { 
     _reportStream.Dispose(); 
    } 

    public void RunReport(IList<Thing> things) 
    { 
     _reportStream = new MemoryStream(); 

     using (FileStream fs = File.OpenRead(_templatePath)) 
     { 
      fs.CopyTo(_reportStream); 
      _reportStream.Seek(0x00000000, SeekOrigin.Begin); 
      fs.Close(); 
     } 

     using (WordprocessingDocument pkgDoc = WordprocessingDocument.Open(_reportStream, true)) 
     { 
      // Set basic properties of the document... 
      pkgDoc.PackageProperties.Creator = "My App"; 
      pkgDoc.PackageProperties.Created = DateTime.Now; 
      pkgDoc.PackageProperties.Title = "Some document"; 
      pkgDoc.PackageProperties.ContentType = "application/msword"; 

      // Read the full document text, in prep for editing... 
      string docText; 
      using (StreamReader sr = new StreamReader(pkgDoc.MainDocumentPart.GetStream())) 
      { 
       docText = sr.ReadToEnd(); 
       sr.Close(); 
      } 

      // Replace the recipient. 
      // Source: https://msdn.microsoft.com/en-us/library/office/bb508261.aspx 
      Regex recipientRegex = new Regex("«Recipient»"); 
      docText = recipientRegex.Replace(docText, things[0].PersonName); 

      // Template has 3 fields in it; replace those fields with details of child data. 
      for (int i = 0; i < 3; i++) 
      { 
       string presentedDate = string.Empty; 
       string presentedNotes = string.Empty; 
       if (i <= things.Count - 1) 
       { 
        var thing = things[i]; 
        presentedDate = thing.thingDate.ToString("MM/dd/yyyy"); 
        presentedNotes = thing.Notes; 
       } 

       string dateReplaceText = string.Format("«ThingDate{0}»", i + 1); 
       Regex dateRegex = new Regex(dateReplaceText); 
       docText = dateRegex.Replace(docText, presentedDate); 

       string noteReplaceText = string.Format("«ThingNote{0}»", i + 1); 
       Regex noteRegex = new Regex(noteReplaceText); 
       docText = noteRegex.Replace(docText, presentedNotes); 
      } 

      // Write the modified document to the stream. 
      using (StreamWriter sw = new StreamWriter(pkgDoc.MainDocumentPart.GetStream(FileMode.Create))) 
      { 
       sw.Write(docText); 
       sw.Close(); 
      } 

      // Close the unmanaged resource! 
      pkgDoc.Close(); 
     } 
    } 

    public byte[] Export() 
    { 
     return _reportStream.ToArray(); 
    } 

    #endregion Methods 
}  

ich habe noch nie versucht, auf einmal eine Word-Vorlage über mehrere Dateneinträge zu verwenden. Da dies eine Technologie ist, mit der der Rest meines Teams die gleiche Erfahrung hat, kann ich sie nicht fragen, wie sie das tun sollen, da sie genau so viel wissen wie ich.

Ich habe die Open XML API for word documents, und einige andere erforderliche Google sucht auf, wie man die Open XML-API zu tun, um dies zu tun ... aber ich fand nichts, das ich Sinn machen könnte.

Frage: Auf welche Weise kann ich eine List<Thing> mit einer variablen Anzahl von Mitgliedern nehmen und Open XML verwenden, um eine MS Word-Vorlage zu nehmen, ein Dokument zu erzeugen, die eine Anzahl von Seiten gleich der Anzahl von Mitgliedern, alle mit dem exakt gleichen Format?

+0

Eigentlich sollten Sie sich zunächst damit vertraut machen, wie Sie Ihr Ergebnis am besten in der Benutzeroberfläche von Word abrufen können. Damit meine ich zu analysieren, wie man dies mit den eingebauten Funktionen von Word erreicht - denn das verwenden Sie auch in Open XML (oder Automatisierung - macht keinen Unterschied). Zum Beispiel, sollte dies im Tabellenformat im Umrissformat sein? Was sollte bestimmen, wie eine Seite bricht - Word verfügt über Formateinstellungen, die Sie in Stile integrieren können, um einen "reibungslosen Ablauf" zu erzielen. Welche andere Formatierung ist erforderlich? –

+0

Sobald Sie ein nützliches Format haben, erstellen Sie ein minimales Dokument, das alle Elemente (einschließlich Stile) enthält. Speichern Sie das Dokument und öffnen Sie es im Open XML SDK Productivity Tool. Das zeigt Ihnen das zugrunde liegende Word Open XML, aus dem das Dokument besteht, sowie den Open XML SDK-Code, um es zu generieren (wenn Sie dieses Tool verwenden möchten). Das sollte dir einen Ausgangspunkt geben. Und wenn Sie die zugrunde liegende XML-Datei sehen, die Ihnen wahrscheinlich sagt, wie Sie Ihre Listendaten "transformieren" können ... –

+0

Ich glaube nicht, dass Sie meine Frage wirklich gelesen haben. Während ich das Tool heruntergeladen und mein Vorlagendokument darin geöffnet habe, sehe ich eine Menge Kauderwelsch und keine klaren Möglichkeiten, meine einzelne Seite zu übernehmen, repliziere diese Seite so oft wie nötig und ersetze den Platzhaltertext auf diesen Seiten mit den Details meiner Objekte. ** Vielleicht ** Open XML ist nicht die richtige Technologie für das, was ich versuche - ich weiß nicht wirklich viel darüber - aber ich würde gerne wissen, dass das, was ich mache, entweder möglich oder unmöglich ist . –

Antwort

2

Ich empfehle Ihnen, eine Word-Vorlage mit der Anzahl der Zusammenführungsfelder zu erstellen, um mit Mitgliedern Ihres Thing/Objekts zuzuordnen und führen Sie dann Seriendruck mit Liste.

Mit DocIO Bibliothek von Syncfusion können Sie es sehr einfach erreichen. DocIO ist eine .NET-Bibliothek, die Word 2003/2007/2010/2013/2016-Dateien liest und schreibt. Die gesamte Palette von Kontrollen ist kostenlos (kommerzielle Anwendungen auch) über die community license program, wenn Sie qualifizieren. Die Community-Lizenz ist das vollständige Produkt ohne Einschränkungen oder Wasserzeichen.

Lassen Sie uns zum Beispiel eine Word-Dokumentvorlage erstellen, wie unten gezeigt, mit Seriendruckfeldern und betrachten Sie eine Liste von Kunden (Liste) Details.

Input Word template

Schritt 1: Erstellen Sie eine Konsolenanwendung
Schritt 2: In Bezug auf Syncfusion.DocIO.Base, Syncfusion.Compression.Base und Syncfusion.OfficeChart.Base
Sie hinzufügen diese Referenz auf Ihr Projekt mit NuGet auch.
Schritt 3: Kopieren Sie & fügen Sie das folgende Code-Snippet ein. Stellen Sie sicher, dass Sie die Vorlage für das Eingabewort richtig beziehen.

Dieser Code erzeugt das Dokument gemäß Ihrer Anforderung, für jede Sache/Kunden wird es eine separate Seite im resultierenden Word-Dokument erzeugen.

Download Demo

using System.Collections.Generic; 
using Syncfusion.DocIO.DLS; 
using Syncfusion.DocIO; 

namespace DocIO_MailMerge 
{ 
    class Program 
    { 
    static void Main(string[] args) 
    { 
     List<Customer> customers = new List<Customer>(); 
     customers.Add(new Customer("Maria", "Anders", "[email protected]", "USA")); 
     customers.Add(new Customer("Ana", "Trujillo", "[email protected]", "USA")); 
     customers.Add(new Customer("Antonio", "Moreno", "[email protected]", "UK")); 
     customers.Add(new Customer("Thomas", "Hardy", "[email protected]", "Mexico")); 

     using (WordDocument wordDocument = new WordDocument(@"Template.docx")) 
     { 
      wordDocument.MailMerge.Execute(customers); 
      wordDocument.Save("Result.docx", FormatType.Docx); 
     } 

     System.Diagnostics.Process.Start("Result.docx"); 
    } 
} 
class Customer 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string MailID { get; set; } 
    public string Country { get; set; } 
    public Customer(string firstName, string lastName, string emailID, string country) 
    { 
     FirstName = firstName; 
     LastName = lastName; 
     MailID = emailID; 
     Country = country; 
    } 
} 
} 

Anmerkung: Ich für Syncfusion arbeiten.