Como faço para converter arquivos do Word em PDF programaticamente? [fechadas]

221

Encontrei vários programas de código-fonte aberto / freeware que permitem converter arquivos .doc em arquivos .pdf, mas eles são todos da variedade de aplicativos / drivers de impressora, sem SDK anexado.

Eu encontrei vários programas que possuem um SDK que permite converter arquivos .doc em arquivos .pdf, mas todos eles são do tipo proprietário, US $ 2.000 por licença ou algo parecido.

Alguém conhece alguma solução programática limpa e barata (de preferência gratuita) para o meu problema, usando C # ou VB.NET?

Obrigado!

Shaul Behr
fonte
1
Verifique se o Pandoc possui ligações para o seu idioma favorito . A interface da linha de comando também é extremamente fácilpandoc manual.docx -o manual.pdf
Coronel Panic
Além disso, verifique o GemBox.Document SDK. Tem uma versão gratuita e uma versão barata. Ele não usa nem um driver de impressora nem o ms office para converter arquivos do Word em PDF.
hertzogth 11/02
Você pode usar o docx2pdf para fazer essa conversão: github.com/AlJohri/docx2pdf
Al Johri

Respostas:

204

Use um loop foreach em vez de um loop for - ele resolveu meu 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++;
}

Aqui está uma modificação de um programa que funcionou para mim. Ele usa o Word 2007 com o suplemento Salvar como PDF instalado. Ele pesquisa em um diretório por arquivos .doc, abre-os no Word e os salva como PDF. Observe que você precisará adicionar uma referência ao Microsoft.Office.Interop.Word à solução.

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
fonte
3
Obrigado! Eu posso apenas usar o Aspose de qualquer maneira, se for mais rápido que a automação do Word. Mas se eu puder tolerar um pouco de lentidão, usarei a sua solução com presteza. Obrigado novamente!
Shaul Behr
4
Sim, não é o mais rápido, mas é difícil superar o preço. :-) Ainda bem que pude ajudar.
Eric Ness
10
Com o Office 2007 SP2, você não precisa mais salvar como download de PDF. Eu também usei essa técnica com sucesso para Excel e Powerpoint.
RichardOD
5
Você usou esse método em um servidor com um aplicativo da web? Estou recebendo muitos problemas, sem mencionar que não é recomendado pelo MS. support.microsoft.com/default.aspx?scid=kb;EN-US;q257757#kb2 Ouvi dizer que o ASPose é ótimo, mas é bastante caro.
Prabu
6
Hum ... se o word não estiver instalado, acho que empacotar o conjunto de interoperabilidade será a menor das suas preocupações. Este código requer a palavra a ser instalada.
BrainSlugs83
35

Para resumir para os usuários do vb.net, a opção gratuita (deve ter o escritório instalado):

Download de montagens do Microsoft office:

Exemplo 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
fonte
3
Ainda funciona em 2015. Com o Office 2013, você não precisa baixar o PIA separadamente.
Adam Anderson
3
E BOOM se abre um messagebox e pede alguma coisa - por exemplo, em uma aplicação web ... ou faz 2 documentos, ao mesmo tempo ...
Stefan Steiger
Uma opção freemium (via nodejs e edge.js, ou Javascript.NET) é npmjs.com/package/@nativedocuments/docx-wasm (Não há necessidade de Word)
JasonPlutext
14

O PDFCreator possui um componente COM, que pode ser chamado de .NET ou VBScript (exemplos incluídos no download).

Mas, parece-me que uma impressora é exatamente o que você precisa - basta misturar isso com a automação do Word e você deve estar pronto.

Mark Brackett
fonte
onde está esse componente COM? E o que significa "mik"? Isso era para ser "mix"?
Shaul Behr
O componente COM está incluído no download, junto com exemplos. E sim, isso deveria ser "mix".
22878 Mark Brackett #
4
FYI - se você seguir esse caminho, o PDFCreator agrupa malware no instalador. Este tem sido um problema contínuo com o PDFCreator desde 2009.
Phil Gorley 28/15
2
@PhilGorley Malware? e esta resposta é +8 ...
MZN
@Mzn - FWIW, prestar atenção e desmarcar a instalação do complemento sempre funciona para mim. Não o vejo como diferente do pacote Oracle porcaria no instalador Java; é irritante, mas não vale a pena evitar o software para mim (sim, ok, o adware do PDFCreator é provavelmente infinitamente menos útil e mais intrusivo do que o que a Oracle está promovendo hoje em dia ... ainda não quero nenhum deles).
Mark Brackett
12

Só queria acrescentar que eu usei as bibliotecas Microsoft.Interop, especificamente a função ExportAsFixedFormat que não vi usada neste segmento.

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
fonte
7
Apenas uma observação para aqueles que não sabem que você precisa do Office instalado na máquina para usar as bibliotecas da Microsoft Interop.
Sam Rueby 23/02
Agradável! Sugiro configurar app.Visible = false;e adicionar uma chamada app.Quit();no bloco final.
Dan Korn
5

Eu passei pela dor do Word para PDF quando alguém me largou com 10000 arquivos de palavras para converter em PDF. Agora eu fiz isso em C # e usei a interoperabilidade do Word, mas foi lento e travou se eu tentasse usar o PC de todo .. muito frustrante.

Isso me levou a descobrir que eu poderia despejar interoperações e sua lentidão ..... para Excel eu uso (EPPLUS) e então descobri que você pode obter uma ferramenta gratuita chamada Spire que permite a conversão para PDF ... com limitações!

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

Ggalla1779
fonte
Obrigado por isso - ótima solução sem usar o Interop. Por que é tão difícil encontrar um conversor gratuito de docx para PDF?
Mdavis
Eu tinha grandes esperanças nisso, mas a versão gratuita é limitada a 3 páginas de saída em PDF. A versão completa é muito cara se você precisar de implantações ilimitadas.
grinder22
O grinder22 GemBox.Document também possui uma versão gratuita com limitação de tamanho e uma versão paga. No entanto, inclui uma implantação isenta de royalties, para que você possa criar e publicar um número ilimitado de projetos sem nenhum custo extra.
hertzogth 11/02
3

Código e solução fáceis usando Microsoft.Office.Interop.Wordpara converter WORD em 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);

}

Adicione este procedimento para liberar memória:

private void releaseObject(object obj)
{
  try
  {
      System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
      obj = null;
  }
  catch (Exception ex)
  {
      //TODO
  }
  finally
  {
     GC.Collect();
  }
}
daniele3004
fonte
É necessário ligar para GC.Collect? Não existe uma maneira diferente de marcar apenas a parte da memória relacionada a isso para liberar no próximo GC automático?
Preza8 30/01
2

Parece haver algumas informações relevantes aqui:

Convertendo documentos do MS Word para PDF no ASP.NET

Além disso, com o Office 2007 tendo a funcionalidade de publicação em PDF, acho que você poderia usar a automação de escritório para abrir o arquivo * .DOC no Word 2007 e Salvar como PDF. Não gosto muito de automação de escritório, pois é lento e propenso a travar, mas apenas jogue isso lá fora ...

MikeW
fonte
Aspose pode funcionar, mas é muito caro.
Shaul Behr
1

O suplemento Microsoft PDF para Word parece ser a melhor solução no momento, mas você deve levar em consideração que ele não converte todos os documentos do Word corretamente em pdf e, em alguns casos, você verá uma enorme diferença entre a palavra e o PDF de saída. Infelizmente, não consegui encontrar nenhuma API que converta todos os documentos do Word corretamente. A única solução que encontrei para garantir que a conversão estava 100% correta foi convertendo os documentos através de um driver de impressora. A desvantagem é que os documentos são enfileirados e convertidos um por um, mas você pode ter certeza de que o pdf resultante é exatamente igual ao layout do documento do Word. Pessoalmente, preferi usar o UDC (conversor universal de documentos) e instalei o Foxit Reader (versão gratuita) no servidor e depois imprimi os documentos iniciando um "Processo" e configurando a propriedade Verb para "imprimir".

Arvand
fonte