c# - que - plantillas personalizadas de office
Cómo crear documentos de Word programáticamente a partir de una plantilla (6)
Agregue referencias para Document.OpenXml.dll
y 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
{
}
}
Estoy tratando de crear unos 600 informes en Microsoft Office Word. Los documentos se completan con datos de una base de datos e imágenes encontradas en un disco local. Me he dado cuenta de que podría crear un proyecto de plantilla de Word en visual studio 2010 y programar la plantilla, de modo que cuando ingrese un valor único (número de identificación), rellene automáticamente todo el documento.
Estoy bastante seguro de que esto es posible. el único problema es. ¿Cómo hago un bucle a través de todas las entradas en la base de datos, abro un nuevo documento basado en la plantilla y establezco el valor de 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");
}
Se supone que la aplicación se ejecuta solo una vez, generando los informes, y no tiene que ser rápida. Solo tiene que ser fácil de desarrollar.
El problema aquí es que parece que el objeto DocumentBase no es accesible fuera del proyecto de Word. El sustituto Microsoft.Office.Interop.Word.Document no tiene una funcionalidad como SelectContentControlsByTitle que me permite encontrar y configurar mis Controles de contenido. Y eso es exactamente lo que necesito hacer ..
Así es como se ve mi código ahora para insertar el texto en mi campo: 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");
Luego, un controlador de eventos en mi plantilla en BeforeSave completa el documento basado en el texto del objeto titulado MyCCTitle.
Con respecto a las respuestas anteriores, estoy de acuerdo con J. Vermeire en que OpenXML es el camino a seguir. He estado usando un kit de herramientas basado en OpenXML durante más de tres años, que produce documentos .docx, combinados a partir de plantillas y datos de bases de datos. Hay un ejemplo de cómo usarlo here . El ejemplo muestra cómo trabajar con un documento a la vez, para trabajar con más de ellos, simplemente agregue un bucle y llame a un método para la generación de documentos.
Debería leer sobre el formato OpenXML si está utilizando el formato Word 2007 o 2010
http://msdn.microsoft.com/en-us/library/bb264572(office.12).aspx
No utilice Office Automation. La automatización de la oficina abre una instancia de la oficina en segundo plano y realiza las acciones en ella. Abrir una instancia de oficina 600 veces no parece ser algo muy interesante. (y nunca se ejecutaría al lado del servidor)
Echa un vistazo a Open XML. Puedes encontrar un montón sobre esto a continuación:
edición: Openxmldeveloper se está cerrando. Encuentre todas las fuentes mencionadas anteriormente en http://www.ericwhite.com/ lugar.
Parece que hay 2 preguntas aquí:
¿Cómo se inicia el proceso para un valor de ID particular?
¿Cómo se rellena el documento?
sunilp ha respondido Q2. Los controles de contenido enlazado de datos son la mejor manera de inyectar datos para Word 2007 y versiones posteriores.
El enfoque de OP parece ser Q1.
No hay un interruptor de línea de comando que le permita pasar un valor arbitrario a Word: http://support.microsoft.com/kb/210565
Así que como lo veo tienes 4 opciones:
haga todo el trabajo a través del SDK de OpenXML, nunca abra Word (como han sugerido otros carteles)
cree un documento preexistente mínimo (que contenga su número de identificación) utilizando el SDK de OpenXML, luego abra Word
automatice Word para pasar el número de identificación al documento, tal vez como una propiedad del documento
hacer el trabajo para crear los 600 documentos en Word usando VSTO o macros de Word (VBA)
¿Yo? Yo crearía un docx que contenga controles de contenido enlazado de datos en Word y lo guardaría.
Luego, en inyectaría mis datos en ella como una parte xml personalizada y la guardaría. (Este paso lo podrías hacer usando el SDK de OpenXML o en Word si necesitas que Word actualice los enlaces para algún proceso posterior del tuyo)
Tal vez debería estar mirando Microsoft.Office.Tools.Word.Document?