it-swarm.dev

Come creare documenti Word a livello di codice da un modello

Sto cercando di creare circa 600 report in Microsoft Office Word. I documenti sono popolati con i dati di un database e le immagini trovate su un'unità locale. Ho capito che potrei creare un progetto di modelli di Word in Visual Studio 2010 e programmare il modello, in modo che quando inserisci un singolo valore (numero identificativo), riempie automaticamente l'intero documento.

Sono abbastanza fiducioso che questo è possibile. l'unico problema è Come faccio a scorrere tutte le voci nel database, aprire un nuovo documento basato sul modello e impostare il valore dell'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'applicazione dovrebbe funzionare una sola volta, generando i report e non deve essere veloce. Deve essere facile da sviluppare.

Il problema qui è che sembra che l'oggetto DocumentBase non sia accessibile al di fuori del progetto Word. Il sostituto Microsoft.Office.Interop.Word.Document non ha funzionalità come SelectContentControlsByTitle che mi consente di trovare e impostare i miei ContentControls. E questo è esattamente quello che devo fare ..

Ecco come appare ora il mio codice per inserire il testo nel mio campo: App Word.Application = 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");

Quindi un eventhandler sul mio modello su BeforeSave compila il documento in base al testo nell'oggetto titolato MyCCTitle.

17
Jesper Kihlberg

Forse dovresti dare un'occhiata a Microsoft.Office.Tools.Word.Document? 

Document.SelectContentControlsByTitle

6
Foole

Non utilizzare Office Automation. Office automation apre un'istanza di office in background ed esegue le azioni su di essa. Aprire 600 volte un'istanza dell'ufficio non sembra una cosa molto interessante da fare. (e non funzionerebbe mai sul lato server)

Dai un'occhiata a Open XML. Puoi trovare dei carichi al riguardo qui sotto:

http://openxmldeveloper.org/

modifica: Openxmldeveloper si sta spegnendo. Trova tutte le fonti menzionate sopra in http://www.ericwhite.com/ invece.

12
Jens

Si dovrebbe leggere sul formato OpenXML se si utilizza il formato Word 2007 o 2010

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

5
Shuwaiee

Sembra che ci siano 2 domande qui:

  1. Come si avvia la procedura per un particolare valore di identificazione

  2. Come si popola il documento.

sunilp ha risposto a Q2. I controlli del contenuto associati ai dati rappresentano il modo migliore per inserire dati per Word 2007 e versioni successive.

L'attenzione dell'OP sembra essere Q1. 

Non esiste alcuna opzione della riga di comando che consente di passare un valore arbitrario a Word: http://support.Microsoft.com/kb/210565

Così come lo vedo hai 4 scelte:

  1. fai tutto il lavoro tramite l'SDK OpenXML, non aprendo mai Word (come suggerito da altri poster)

  2. crea un documento preesistente minimo (contenente il tuo numero identificativo) usando l'SDK OpenXML, quindi apri Word

  3. automatizza Word per passare il numero ID al documento, forse come proprietà del documento 

  4. fai il lavoro per creare i 600 documenti in Word usando VSTO o Word macros (VBA)

Me? Vorrei creare un docx contenente i controlli del contenuto associati ai dati in Word e salvarlo.

Quindi, inserisce i miei dati in esso come una parte xml personalizzata e li salva. (Questo passo si può fare usando l'SDK di OpenXML, o in Word se è necessario che Word aggiorni i collegamenti per alcuni dei tuoi processi downstream)

3
JasonPlutext

Per quanto riguarda le risposte sopra, sono d'accordo con J. Vermeire che OpenXML è la strada da percorrere. Ho utilizzato un toolkit basato su OpenXML da oltre tre anni, che produce documenti .docx, uniti da modelli e dati di database. C'è un esempio su come usarlo qui . L'esempio mostra come lavorare con un documento alla volta, per lavorare con più di essi, basta aggiungere un ciclo e chiamare un metodo per la generazione di documenti.

0
Phil Grant

Aggiungi riferimenti per Document.OpenXml.dll e 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