2010-11-29 2 views
14

Я пытаюсь создать около 600 отчетов в Microsoft Word Word. Документы заполняются данными из базы данных и изображениями, найденными на локальном диске. Я выяснил, что я мог бы создать проект Word Template в visual studio 2010 и запрограммировать шаблон, чтобы при вводе единственного значения (id-number) он автоматически заполнял весь документ.Как создать текстовые документы программным путем из шаблона

Я вполне уверен, что это возможно. единственная проблема. Как мне перебирать все записи в базе данных, открывать новый документ на основе шаблона и устанавливать значение 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"); 
} 

Приложение должно работать только один раз, генерируя отчеты, и это не должно быть быстрым. Его просто нужно легко развить.

Проблема заключается в том, что объект DocumentBase не доступен вне проекта Word. Подменю Microsoft.Office.Interop.Word.Document не имеет таких функций, как SelectContentControlsByTitle, что позволяет мне находить и устанавливать мои ContentControls. И это именно то, что мне нужно сделать.

Это мой код выглядит как сейчас, чтобы вставить текст в мое поле: 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"); 

Тогда EventHandler на моем шаблоне на BeforeSave заполняет документ, основанный на тексте в MyCCTitle названием объекта.

ответ

4

Вы должны читать о формате OpenXML, если вы используете Word 2007 или 2010 Формат

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

+0

это было бы излишним за то, что он пытается достичь, Word автоматизации/Interop гораздо проще сделать для этого сценария. – BrokenGlass 2010-11-29 13:44:05

+0

Overkill? Не за что. OpenXML SDK с легкостью работает и предназначен именно для этого. Вам не нужно, чтобы Word был установлен на вашем сервере при выполнении автоматизации слова/взаимодействия? С OpenXML вы этого не делаете. – 2010-11-29 13:58:27

+0

Плюс я хочу добавить комментарий Moontear, формат OpenXML - это просто XML так быстро, что он пытается сделать (создавая 600 документов) – Shuwaiee 2010-11-29 14:40:29

9

Не использовать автоматизации Office. Офисная автоматизация открывает экземпляр офиса в фоновом режиме и выполняет действия на нем. Открытие экземпляра офиса 600 раз не кажется очень интересной задачей. (и он никогда не будет работать с серверами)

Взгляните на Open XML. Вы можете найти нагрузок об этом ниже:

http://openxmldeveloper.org/

2

Кажется, что есть 2 вопроса здесь:

  1. Как вы запустить процесс для конкретного Ид значения

  2. Как вы заполняете документ.

sunilp ответил Q2. Элементы управления содержимым с привязкой к данным - лучший способ для ввода данных для Word 2007 и более поздних версий.

Ориентация OP - это Q1.

Там нет командной строки, что позволяет передавать произвольное значение слова: http://support.microsoft.com/kb/210565

Так как я вижу у вас есть 4 варианта:

  1. делать всю работу по OpenXML SDK , никогда не открывая Word вообще (как предлагали другие плакаты)

  2. создать минимально существующий документ (содержащий номер вашего идентификатора) с помощью OpenXML SDK, затем откройте Word

  3. автоматизировать слово передать номер документа к документу, возможно, в качестве свойства документа

  4. сделать работу по созданию 600 документов в слово с помощью VSTO или макросов Word (VBA)

Me ? Я бы создал docx, содержащий связанные с данными элементы управления содержимым в Word, и сохранил его.

Затем, введя мои данные в него как пользовательскую часть xml и сохраните ее. (Этот шаг, который вы могли бы сделать, используя OpenXML SDK или Word, если вам нужно, чтобы Word обновлял привязки для вашего последующего процесса)

0

В отношении ответов выше, я согласен с Дж VERMEIRE, что OpenXML является путь. Я уже более трех лет использую инструментарий на базе OpenXML, который создает документы .docx, объединенные с шаблонами и данными базы данных. Пример использования here. В этом примере показано, как работать с одним документом в то время, работать с большим количеством из них, просто добавить цикл и вызвать метод генерации документа.

0

Добавить ссылки на Document.OpenXml.dll и 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 
     { 

     } 
    } 
Смежные вопросы