J'ai une application de formulaires Web ASP.NET 4.5, exécutée sur un IIS 7.5. J'essaie de générer un document Word à partir de l'une de ses pages où j'ai un formulaire personnalisé.Générer un document Word via OpenXML
J'ai téléchargé un modèle de document Word qui contient des champs de fusion. Dans le code derrière, je veux remplir les champs de fusion en fonction des requêtes de base de données sql.
Pour certains champs de fusion, j'ai besoin d'insérer plusieurs lignes de texte. Certains d'entre eux ont même des listes à puces. Ces fragments de texte ne peuvent pas être stockés dans sql. Je les ai donc ajoutés dans un document Word séparé avec des signets.
Donc, pour récapituler:
Template.dotx -> contient les champs de fusion
Data.docx -> contient les fragments de texte qui ont été marqués avec des signets.
J'ai réussi à remplacer les champs de fusion de Template.dotx avec l'utilisation d'OpenXML, mais je ne trouve pas un moyen d'obtenir les données des signets dans les champs de fusion.
Cela fonctionne très bien avec Interop, mais j'ai eu des problèmes lorsque je l'ai téléchargé sur le serveur, donc je suis passé à OpenXML.
C'est ce que je l'ai essayé jusqu'à présent:
private string GetBookmarkData(WordprocessingDocument secondWordDoc, string bookmarkKey)
{
string returnVal = "";
foreach (BookmarkStart bookmarkStart in secondWordDoc.MainDocumentPart.RootElement.Descendants<BookmarkStart>())
{
if(bookmarkStart.Name == bookmarkKey)
{
foreach(Run run in bookmarkStart.Parent.Descendants<Run>())
{
returnVal += run.Descendants<Text>().FirstOrDefault().Text + "<br/>";
}
}
}
return returnVal;
}
protected void PrintBtn_Click(object sender, EventArgs e)
{
string mainTemplate = Server.MapPath("~/MyFolder/Template.dotx");
string savePath = Server.MapPath("~/SaveFolder/Final.docx");
File.Copy(mainTemplate, savePath);
using(WordprocessingDocument firstDoc = WordprocessingDocument.Open(savePath, true))
{
using (WordprocessingDocument secondDoc = WordprocessingDocument.Open(Server.MapPath("~/MyFolder/Data.docx"), true))
{
foreach (FieldCode field in firstDoc.MainDocumentPart.RootElement.Descendants<FieldCode>())
{
var fieldNameStart = field.Text.LastIndexOf(" MERGEFIELD", System.StringComparison.Ordinal);
String fieldText = field.InnerText;
if (fieldText.StartsWith(" MERGEFIELD"))
{
Int32 endMerge = fieldText.IndexOf("\\");
Int32 fieldNameLength = fieldText.Length - endMerge;
String fieldName = fieldText.Substring(11, endMerge - 11);
fieldName = fieldName.Trim();
string autoFill = "";
switch (fieldName)
{
case "MergeField1":
autoFill = mergefield_1;
break;
case "MergeField2":
autoFill = mergefield_2;
break;
case "MergeField3":
autoFill = GetBookmarkData(secondDoc, "Bookmark1");
break;
case "MergeField4":
autoFill = GetBookmarkData(secondDoc, "Bookmark2");
break;
case "MergeField5":
autoFill = GetBookmarkData(secondDoc, "Bookmark3");
break;
}
}
foreach (Run run in firstDoc.MainDocumentPart.Document.Descendants<Run>())
{
foreach (Text txtFromRun in run.Descendants<Text>().Where(a => a.Text == "«" + fieldName + "»"))
{
txtFromRun.Text = autoFill;
}
}
}
}
}
firstDoc.ChangeDocumentType(WordprocessingDocumentType.Document);
firstDoc.MainDocumentPart.Document.Save();
}
}
Alors qu'est-ce que cela fait?
Lorsque je clique sur un bouton, j'appelle la méthode PrintBtn_Click. Après avoir fait de la magie SQL (que je n'ai pas incluse dans ceci), j'initialise certaines variables qui rempliront chaque champ de fusion. Cet exemple est une version courte et modifiée. L'original est beaucoup plus gros. En utilisant ce code, j'ai réussi à remplir les champs de fusion. Cela fonctionne très bien. Cependant la méthode: `
string GetBookmarkData(WordprocessingDocument secondWordDoc, string bookmarkKey)`
Ne fait pas vraiment ce qu'il est censé faire. Il devrait aller dans le fichier Data.docx, récupérer tout le texte du signet que j'ai spécifié. Il retourne uniquement les lignes qui n'ont pas de puces ou de formatage bizarre.
J'ai utilisé le même processus en utilisant Interop et je n'ai eu aucun problème. Comment puis-je faire cela avec OpenXML? Les lignes contenant des puces sont-elles stockées dans un fichier XML différent?
J'ai essayé de récupérer tous les Runs entre BookmarkStart et BookmarkEnd et d'en extraire le texte.
Toute aide est appréciée. Merci!
Mise à jour
Le secondDoc est en fait la Data.docx et ressemble à ceci:
Bookmark1
• Text-Information 1 (This is just an example)
• Text-Information 2 (This is just an example)
• Text-Information 3 (This is just an example)
• Text-Information 4 (This is just an example)
Bookmark2
This is a list of multiple items:
Item 1 x.000,00
Item 2 x.000,00
Item 3 x.000,00
Item 4 x.000,00
Item 5 000,00
This is the conclusion for this list.
Following is a list of other multiple items:
Item 1 x.000,00
Item 2 x.000,00
Item 3 x.000,00
Item 4 x.000,00
Item 5 000,00
This is the conclusions for this list
Bookmark3
a) Another example of text that needs to go in the mergefield:
• Article 1 xxxx Quantity/Producer etc
• Article 2 xxxx Quantity/Producer etc
Some details about this block of text that is not relevant but I need to insert it in the merge field as well
Ainsi, le texte entier après "Bookmark1"/"Bookmark2"/"Bookmark3", doit aller dans leurs champs de fusion spécifiques, si un certain radiobutton est pressé. J'ai mis en signet ces blocs de texte. Comme je vous l'ai dit plus haut, il n'insère que des lignes qui n'ont pas de puces.Par exemple, le champ de fusion qui correspond à Bookmark2, reçoit uniquement "Ceci est une liste de plusieurs éléments:".
Afin de mieux vous aider, nous aurons besoin de voir secondDoc. Une fois que nous pouvons voir la structure, nous pouvons vous aider à résoudre votre code. – Taterhead
J'ai mis à jour le message initial. J'espère que c'est clair. Je vous remercie! – Cosmos24Magic
C'est clair, mais pas assez clair. Nous avons besoin du document pour inspecter la structure xml exacte. Cela aidera à déterminer pourquoi votre méthode ne renvoie pas les valeurs correctes. Si vous ne voulez pas ou ne pouvez pas partager le fichier, je comprends. Ce que vous devez faire est de télécharger l'outil de productivité OpenXML (https://www.microsoft.com/en-us/download/details.aspx?id=30425) et l'utiliser pour ouvrir le document pour inspecter la structure xml. Puis réécrivez votre méthode GetBookmarkData en fonction de la structure. Si vous postez le document, nous le ferons pour vous;) – Taterhead