¿Cómo convierto archivos de Word a PDF mediante programación? [cerrado]

221

He encontrado varios programas de código abierto / freeware que le permiten convertir archivos .doc a archivos .pdf, pero todos son de la variedad de controladores de aplicaciones / impresoras, sin SDK conectado.

He encontrado varios programas que tienen un SDK que le permite convertir archivos .doc a archivos .pdf, pero todos son del tipo propietario, $ 2,000 por licencia o por ahí.

¿Alguien sabe de alguna solución programática limpia y económica (preferiblemente gratuita) para mi problema, usando C # o VB.NET?

¡Gracias!

Shaul Behr
fuente
1
Compruebe si Pandoc tiene enlaces para su idioma favorito . La interfaz de la línea de comandos también es muy fácilpandoc manual.docx -o manual.pdf
Coronel Panic
Además, consulte GemBox.Document SDK. Tiene una versión gratuita y una versión económica. No utiliza ni un controlador de impresora ni ms office para convertir archivos de Word a PDF.
hertzogth
Puede usar docx2pdf para hacer esta conversión: github.com/AlJohri/docx2pdf
Al Johri

Respuestas:

204

Use un bucle foreach en lugar de un bucle for: resolvió mi problema.

int j = 0;
foreach (Microsoft.Office.Interop.Word.Page p in pane.Pages)
{
    var bits = p.EnhMetaFileBits;
    var target = path1 +j.ToString()+  "_image.doc";
    try
    {
        using (var ms = new MemoryStream((byte[])(bits)))
        {
            var image = System.Drawing.Image.FromStream(ms);
            var pngTarget = Path.ChangeExtension(target, "png");
            image.Save(pngTarget, System.Drawing.Imaging.ImageFormat.Png);
        }
    }
    catch (System.Exception ex)
    {
        MessageBox.Show(ex.Message);  
    }
    j++;
}

Aquí hay una modificación de un programa que funcionó para mí. Utiliza Word 2007 con el complemento Guardar como PDF instalado. Busca en un directorio archivos .doc, los abre en Word y luego los guarda como PDF. Tenga en cuenta que deberá agregar una referencia a Microsoft.Office.Interop.Word a la solución.

using Microsoft.Office.Interop.Word;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

...

// Create a new Microsoft Word application object
Microsoft.Office.Interop.Word.Application word = new Microsoft.Office.Interop.Word.Application();

// C# doesn't have optional arguments so we'll need a dummy value
object oMissing = System.Reflection.Missing.Value;

// Get list of Word files in specified directory
DirectoryInfo dirInfo = new DirectoryInfo(@"\\server\folder");
FileInfo[] wordFiles = dirInfo.GetFiles("*.doc");

word.Visible = false;
word.ScreenUpdating = false;

foreach (FileInfo wordFile in wordFiles)
{
    // Cast as Object for word Open method
    Object filename = (Object)wordFile.FullName;

    // Use the dummy value as a placeholder for optional arguments
    Document doc = word.Documents.Open(ref filename, ref oMissing,
        ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
        ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
        ref oMissing, ref oMissing, ref oMissing, ref oMissing);
    doc.Activate();

    object outputFileName = wordFile.FullName.Replace(".doc", ".pdf");
    object fileFormat = WdSaveFormat.wdFormatPDF;

    // Save document into PDF Format
    doc.SaveAs(ref outputFileName,
        ref fileFormat, ref oMissing, ref oMissing,
        ref oMissing, ref oMissing, ref oMissing, ref oMissing,
        ref oMissing, ref oMissing, ref oMissing, ref oMissing,
        ref oMissing, ref oMissing, ref oMissing, ref oMissing);

    // Close the Word document, but leave the Word application open.
    // doc has to be cast to type _Document so that it will find the
    // correct Close method.                
    object saveChanges = WdSaveOptions.wdDoNotSaveChanges;
    ((_Document)doc).Close(ref saveChanges, ref oMissing, ref oMissing);
    doc = null;
}

// word has to be cast to type _Application so that it will find
// the correct Quit method.
((_Application)word).Quit(ref oMissing, ref oMissing, ref oMissing);
word = null;
Eric Ness
fuente
3
¡Gracias! De todos modos, puedo ir con Aspose, si es más rápido que la automatización de Word. Pero si puedo tolerar un poco de lentitud, utilizaré su solución. ¡Gracias de nuevo!
Shaul Behr
44
Sí, no es el más rápido, pero es difícil superar el precio. :-) Me alegro de poder ayudar.
Eric Ness
10
Con Office 2007 SP2 ya no necesita guardar como descarga de PDF. También he usado esta técnica con éxito para Excel y Powerpoint.
RichardOD
55
¿Ha utilizado este método en un servidor con una aplicación web? Recibo muchos problemas, sin mencionar que MS no lo recomienda. support.microsoft.com/default.aspx?scid=kb;EN-US;q257757#kb2 Escuché que ASPose es excelente, pero es muy caro.
Prabu
66
Um ... si Word no está instalado, creo que empaquetar el ensamblado de interoperabilidad será la menor de sus preocupaciones. Este código REQUIERE que se instale una palabra.
BrainSlugs83
35

Para resumir para los usuarios de vb.net, la opción gratuita (debe tener Office instalado):

Descarga de ensamblados de Microsoft Office:

Ejemplo de VB.NET:

        Dim word As Application = New Application()
        Dim doc As Document = word.Documents.Open("c:\document.docx")
        doc.Activate()
        doc.SaveAs2("c:\document.pdf", WdSaveFormat.wdFormatPDF)
        doc.Close()
Elger Mensonides
fuente
3
Todavía funciona en 2015. Con Office 2013 no necesita descargar el PIA por separado.
Adam Anderson
3
Y BOOM si abre un cuadro de mensaje y pregunta algo, por ejemplo en una aplicación web ... o hace 2 documentos al mismo tiempo ...
Stefan Steiger
Una opción de freemium (a través de nodejs y edge.js, o Javascript.NET) es npmjs.com/package/@nativedocuments/docx-wasm (No necesita Word)
JasonPlutext
14

PDFCreator tiene un componente COM, invocable desde .NET o VBScript (muestras incluidas en la descarga).

Pero, me parece que una impresora es justo lo que necesita: solo mezcle eso con la automatización de Word , y debería estar listo.

Mark Brackett
fuente
¿Dónde está este componente COM? ¿Y qué significa "mik"? ¿Se suponía que eso era "mezclar"?
Shaul Behr
El componente COM se incluye en la descarga, junto con las muestras. Y sí, se suponía que eso era "mezclar".
Mark Brackett el
44
FYI: si sigue esta ruta, PDFCreator agrupa el malware en el instalador. Este ha sido un problema continuo con PDFCreator desde 2009.
Phil Gorley
2
@PhilGorley Malware? y esta respuesta es +8 ...
Mzn
@Mzn - FWIW, prestar atención y desmarcar las instalaciones de complementos siempre funciona para mí. No lo veo como algo diferente a la basura de agrupamiento de Oracle en el instalador de Java; es molesto, pero no vale la pena evitar el software para mí (sí, está bien, el adware de PdfCreator es probablemente infinitamente menos útil y más intrusivo que lo que sea que Oracle esté impulsando en estos días ... todavía no quiero ninguno de ellos).
Mark Brackett
12

Solo quería agregar que usé las bibliotecas Microsoft.Interop, específicamente la función ExportAsFixedFormat que no vi utilizada en este hilo.

using Microsoft.Office.Interop.Word;
using System.Runtime.InteropServices;
using System.IO;
using Microsoft.Office.Core;

Application app;

public string CreatePDF(string path, string exportDir)
{
    Application app = new Application();
    app.DisplayAlerts = WdAlertLevel.wdAlertsNone;
    app.Visible = true;

    var objPresSet = app.Documents;
    var objPres = objPresSet.Open(path, MsoTriState.msoTrue, MsoTriState.msoTrue, MsoTriState.msoFalse);

    var pdfFileName = Path.ChangeExtension(path, ".pdf");
    var pdfPath = Path.Combine(exportDir, pdfFileName);

    try
    {
        objPres.ExportAsFixedFormat(
            pdfPath,
            WdExportFormat.wdExportFormatPDF,
            false,
            WdExportOptimizeFor.wdExportOptimizeForPrint,
            WdExportRange.wdExportAllDocument
        );
    }
    catch
    {
        pdfPath = null;
    }
    finally
    {
        objPres.Close();
    }
    return pdfPath;
}
zeta
fuente
77
Solo una nota para aquellos que no saben que necesita Office instalado en la máquina para usar las bibliotecas de interoperabilidad de Microsoft.
Sam Rueby
¡Agradable! Sugiero configurar app.Visible = false;y agregar una llamada app.Quit();en el bloque finalmente.
Dan Korn
5

Revisé el dolor de Word a PDF cuando alguien me dejó con 10000 archivos de palabras para convertir a PDF. Ahora lo hice en C # y usé interoperabilidad de Word, pero fue lento y se bloqueó si intenté usar PC en absoluto ... muy frustrante.

Esto me llevó a descubrir que podía volcar interops y su lentitud ..... para Excel que uso (EPPLUS) y luego descubrí que puedes obtener una herramienta gratuita llamada Spire que permite la conversión a PDF ... ¡con limitaciones!

http://www.e-iceblue.com/Introduce/free-doc-component.html#.VtAg4PmLRhE

Ggalla1779
fuente
Gracias por esto - gran solución sin usar Interop. ¿Por qué es tan difícil encontrar un convertidor docx a PDF gratuito?
mbdavis
Tenía muchas esperanzas para esto, pero la versión gratuita está limitada a 3 páginas de salida en PDF. La versión completa es muy costosa si necesita implementaciones ilimitadas.
grinder22
grinder22 GemBox.Document también tiene una versión gratuita con limitación de tamaño y una versión paga. Sin embargo, incluye una implementación libre de regalías para que pueda construir y publicar una cantidad ilimitada de proyectos sin costo adicional.
hertzogth
3

Código y solución fáciles de usar Microsoft.Office.Interop.Wordpara converger WORD en PDF

using Word = Microsoft.Office.Interop.Word;

private void convertDOCtoPDF()
{

  object misValue = System.Reflection.Missing.Value;
  String  PATH_APP_PDF = @"c:\..\MY_WORD_DOCUMENT.pdf"

  var WORD = new Word.Application();

  Word.Document doc   = WORD.Documents.Open(@"c:\..\MY_WORD_DOCUMENT.docx");
  doc.Activate();

  doc.SaveAs2(@PATH_APP_PDF, Word.WdSaveFormat.wdFormatPDF, misValue, misValue, misValue, 
  misValue, misValue, misValue, misValue, misValue, misValue, misValue);

  doc.Close();
  WORD.Quit();


  releaseObject(doc);
  releaseObject(WORD);

}

Agregue este procedimiento para liberar memoria:

private void releaseObject(object obj)
{
  try
  {
      System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
      obj = null;
  }
  catch (Exception ex)
  {
      //TODO
  }
  finally
  {
     GC.Collect();
  }
}
daniele3004
fuente
¿Es necesario llamar a GC.Collect? ¿No hay una manera diferente de marcar solo la parte de la memoria que está relacionada con esto para liberarla en el próximo GC automático?
Preza8
2

Parece ser alguna información relevante aquí:

Convertir documentos de MS Word a PDF en ASP.NET

Además, con Office 2007 con funcionalidad de publicación en PDF, creo que podría usar la automatización de oficina para abrir el archivo * .DOC en Word 2007 y Guardar como PDF. No estoy demasiado interesado en la automatización de oficinas, ya que es lento y propenso a colgar, pero solo lo tiro por ahí ...

MikeW
fuente
Aspose puede funcionar, pero es extremadamente costoso.
Shaul Behr
1

El complemento de Microsoft PDF para Word parece ser la mejor solución por ahora, pero debe tener en cuenta que no convierte todos los documentos de Word correctamente a PDF y, en algunos casos, verá una gran diferencia entre Word y el PDF de salida. Lamentablemente, no pude encontrar ninguna API que convirtiera todos los documentos de Word correctamente. La única solución que encontré para garantizar que la conversión fuera 100% correcta fue convertir los documentos a través de un controlador de impresora. La desventaja es que los documentos se ponen en cola y se convierten uno por uno, pero puede estar seguro de que el PDF resultante es exactamente el mismo que el diseño del documento de Word. Personalmente, preferí usar UDC (convertidor universal de documentos) e instalé Foxit Reader (versión gratuita) en el servidor también, luego imprimí los documentos comenzando un "Proceso" y configurando su propiedad Verb para "imprimir".

Arvand
fuente