web-dev-qa-db-fra.com

Comment créer des documents Word par programme à partir d'un modèle

J'essaie de créer environ 600 rapports dans Microsoft Office Word. Les documents sont remplis avec les données d'une base de données et des images trouvées sur un lecteur local ..__ J'ai découvert que je pouvais créer un projet de modèle Word dans Visual Studio 2010 et programmer le modèle afin que, lorsque vous entrez un valeur unique (id-number), il remplit automatiquement tout le document.

Je suis assez confiant que cela est possible. le seul problème est. Comment puis-je parcourir toutes les entrées de la base de données, ouvrir un nouveau document basé sur le modèle et définir la valeur id?

for(int i = 0; i < idnumbers.Count(); i++)
{
     Word.Application app = new Word.Application();
     Word.Document doc = app.Documents.Add(@"C:\..\WordGenerator\bin\Debug\WordTemplate.dotx");
     //input the id-number below: HOW??

     doc.SaveAs(FileName: @"c:\temp\test.docx"); 
}

L’application est supposée ne fonctionner qu’une seule fois, générant les rapports, et ne doit pas être rapide. Il faut juste que ce soit facile à développer.

Le problème ici est qu'il semble que l'objet DocumentBase n'est pas accessible en dehors du projet Word. Le substitut Microsoft.Office.Interop.Word.Document n'a pas de fonctionnalité comme SelectContentControlsByTitle qui me permet de rechercher et de définir mes ContentControls. Et c'est exactement ce que je dois faire ..

Voici à quoi ressemble mon code pour insérer le texte dans mon champ: Word.Application app = new Word.Application ();

        Word.Document doc = app.Documents.Add(@"C:\..\test.dotx");

        foreach (Word.ContentControl cc in doc.SelectContentControlsByTitle("MyCCTitle"))
        {
            cc.Range.Text += "1234";
        }

        doc.SaveAs(FileName: @"c:\temp\test.docx");

Ensuite, un gestionnaire d'événements sur mon modèle sur BeforeSave remplit le document en fonction du texte contenu dans l'objet intitulé MyCCTitle.

17
Jesper Kihlberg

Peut-être devriez-vous regarder Microsoft.Office.Tools.Word.Document? 

Document.SelectContentControlsByTitle

6
Foole

N'utilisez pas Office Automation . Office Automation ouvre une instance de office en arrière-plan et effectue les actions dessus. Ouvrir une instance de bureau 600 fois ne semble pas une chose très intéressante à faire. (et il ne ferait jamais fonctionner côté serveur)

Jetez un coup d'œil à Open XML. Vous pouvez trouver des charges à ce sujet ci-dessous:

http://openxmldeveloper.org/

edit: Openxmldeveloper est en train de s'arrêter. Trouvez toutes les sources mentionnées ci-dessus sur http://www.ericwhite.com/ à la place.

12
Jens

Vous devriez lire sur le format OpenXML si vous utilisez le format Word 2007 ou 2010

http://msdn.Microsoft.com/en-us/library/bb264572(office.12).aspx

5
Shuwaiee

On dirait qu'il y a 2 questions ici:

  1. Comment lancer le processus pour une valeur id particulière

  2. Comment remplissez-vous le document.

sunilp a répondu à la question Q2. Les contrôles de contenu lié aux données constituent le meilleur moyen d'injecter des données pour Word 2007 et les versions ultérieures.

L'objectif de l'OP semble être Q1. 

Aucun commutateur de ligne de commande ne vous permet de transmettre une valeur arbitraire à Word: http://support.Microsoft.com/kb/210565

Donc, à mon avis, vous avez 4 choix:

  1. faire tout le travail à l'aide du SDK OpenXML, sans jamais ouvrir Word (comme l'ont suggéré d'autres afficheurs)

  2. créez un document pré-existant minimal (contenant votre numéro d'identification) à l'aide du SDK OpenXML, puis ouvrez Word

  3. automatiser Word pour transmettre le numéro d'identification au document, peut-être en tant que propriété de document 

  4. faire le travail pour créer les 600 documents dans Word en utilisant des macros VSTO ou Word (VBA)

Moi? Je créerais un docx contenant des contrôles de contenu liés aux données dans Word et le sauvegarderais.

Ensuite, in injecterait mes données dans une partie XML personnalisée et les sauvegarderait. (Cette étape peut être réalisée à l'aide du SDK OpenXML ou de Word si vous aviez besoin que Word mette à jour les liaisons pour certains de vos processus en aval.)

3
JasonPlutext

En ce qui concerne les réponses ci-dessus, je suis d'accord avec J. Vermeire pour dire qu'OpenXML est la voie à suivre. J'utilise une boîte à outils OpenXML depuis plus de trois ans, qui produit des documents .docx, fusionnés à partir de modèles et de données de base de données. Voici un exemple d'utilisation ici . L'exemple montre comment travailler avec un document à la fois, pour en utiliser plusieurs, il suffit d'ajouter une boucle et d'appeler une méthode pour la génération de document.

0
Phil Grant

Ajouter des références pour Document.OpenXml.dll et WindowsBase.dll 

using System.IO.Packaging;

using DocumentFormat.OpenXml.Packaging;

using System.DirectoryServices;

 protected void btnOK_Click(object sender, EventArgs e)
  {

        try
        {
            Package package;
            string strTemplateName = ddl_Templates.SelectedValue.ToString(); //Select Dotx template 
            string strClaimNo = "3284112";
            string strDatePart = DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Day.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString() + DateTime.Now.Millisecond.ToString();
            //Word template file
            string templateName = Server.MapPath("~\\LetterTemplates\\" + strTemplateName + ".dotx");
            PackagePart documentPart = null;
            //New file name to be generated from 
            string docFileName = Server.MapPath("~\\LetterTemplates\\" + strClaimNo + "_" + strTemplateName + "_" + strDatePart + ".docx");

            File.Copy(templateName,docFileName, true);
            string fileName = docFileName;
            package = Package.Open(fileName, FileMode.Open, FileAccess.ReadWrite);
            DataSet DS = GetDataSet(strClaimNo, ""); // to get the data from backend to fill in for merge fields
            try
            {
                if (DS != null)
                {
                    if (DS.Tables.Count > 0)
                    {
                        if (DS.Tables[0].Rows.Count > 0)
                        {
                            foreach (System.IO.Packaging.PackageRelationship documentRelationship
                                in package.GetRelationshipsByType(documentRelationshipType))
                            {
                                NameTable nt = new NameTable();
                                nsManager = new XmlNamespaceManager(nt);
                                nsManager.AddNamespace("w",
                                  "http://schemas.openxmlformats.org/wordprocessingml/2006/main");

                                Uri documentUri = PackUriHelper.ResolvePartUri(
                                  new Uri("/", UriKind.Relative), documentRelationship.TargetUri);
                                documentPart = package.GetPart(documentUri);

                                //Get document xml
                                XmlDocument xdoc = new XmlDocument();
                                xdoc.Load(documentPart.GetStream(FileMode.Open, FileAccess.Read));
                                int intMergeFirldCount = xdoc.SelectNodes("//w:t", nsManager).Count;

                                XmlNodeList nodeList = xdoc.SelectNodes("//w:t", nsManager);
                                foreach (XmlNode node in nodeList)
                                {
                                    try
                                    {
                                        xdoc.InnerXml = xdoc.InnerXml.Replace(node.InnerText, DS.Tables[0].Rows[0][node.InnerText.Replace("«", "").Replace("»", "").Trim()].ToString());
                                    }catch(Exception x) { }
                                }

                                StreamWriter streamPart = new StreamWriter(documentPart.GetStream(FileMode.Open, FileAccess.Write));
                                xdoc.Save(streamPart);
                                streamPart.Close();
                                package.Flush();
                                package.Close();
                            }
                            using (WordprocessingDocument template = WordprocessingDocument.Open(docFileName, true))
                            {
                                template.ChangeDocumentType(DocumentFormat.OpenXml.WordprocessingDocumentType.Document);
                                template.MainDocumentPart.Document.Save();
                            }

                            byte[] bytes = System.IO.File.ReadAllBytes(docFileName);
                            System.IO.File.Delete(docFileName);
                            System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
                            response.ClearContent();
                            response.Clear();
                            response.ContentType = "application/vnd.msword.document.12"; //"application/msword";
                            Response.ContentEncoding = System.Text.Encoding.UTF8;
                            response.AddHeader("Content-Disposition", "attachment; filename=" + strClaimNo + "_" + strTemplateName + "_" + strDatePart + ".docx;");
                            response.BinaryWrite(bytes);
                            response.Flush();
                            response.Close();
                        }
                        else
                        {
                            throw (new Exception("No Records Found."));
                        }
                    }
                    else
                    {
                        throw (new Exception("No Records Found."));
                    }
                }
                else
                {
                    throw (new Exception("No Records Found."));
                }


            }
            catch (Exception ex)
            {
                package.Flush();
                package.Close();
                // Softronic to add code for exception handling
            }
        }
        catch (Exception ex)
        {

            // add code for exception handling
        }
        finally
        {

        }
    }
0
Sachin Patkar