2011-11-23 22 views
5

Necesito comparar dos documentos de oficina, en este caso dos documentos de Word y proporcionar una diferencia, que es algo similar a lo que se muestra en SVN. No en esa medida, pero al menos ser capaz de resaltar las diferencias.comparando programáticamente documentos de Word

He intentado utilizar la DLL COM oficina y llegado hasta aquí ..

object fileToOpen = (object)@"D:\doc1.docx"; 
string fileToCompare = @"D:\doc2.docx"; 

WRD.Application WA = new WRD.Application(); 

Document wordDoc = null; 

wordDoc = WA.Documents.Open(ref fileToOpen, Type.Missing, Type.Missing, Type.Missing, Type.Missing,  Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); 
wordDoc.Compare(fileToCompare, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); 

Algún consejo sobre la manera de proceder? Esta será una aplicación web con muchos éxitos. ¿Está utilizando el objeto com de office de la manera correcta, o hay otras cosas que pueda ver?

+0

¿Qué tan fácil es mostrar SVN la diferencia entre dos archivos binarios? (AFAIK 'docx' es un formato de archivo zip) – sll

+0

seleccione los dos archivos en cuestión, generalmente en la misma carpeta en el lado del cliente. Tienes tortugaSVN instalada. Haga clic con el botón derecho y vaya al menú TortoiseSVN y seleccione Dif. ... – user20358

+0

Sí, sé cómo hacerlo, pero qué diferencia verá, ¿tiene algún sentido? – sll

Respuesta

1

Estoy de acuerdo con Joseph en diferir la cadena. También recomendaría un motor de diferenciación específico (varios se encuentran aquí: Any decent text diff/merge engine for .NET?) que puede ayudarlo a evitar algunas de las trampas normales en la diferencia.

0

Realmente debería extraer el documento en una cadena y diferir eso.

Solo le importan los cambios de texto y no el formato, ¿verdad?

+1

todo, incluso si la imagen es diferente. Pero voy a tratar de relajar ese requisito. – user20358

3

Debe usar la clase de documento para comparar archivos y abrir en un documento de Word el resultado.

using OfficeWord = Microsoft.Office.Interop.Word; 

object fileToOpen = (object)@"D:\doc1.docx"; 
string fileToCompare = @"D:\doc2.docx"; 

var app = Global.OfficeFile.WordApp; 

object readOnly = false; 
object AddToRecent = false; 
object Visible = false; 

OfficeWord.Document docZero = app.Documents.Open(fileToOpen, ref missing, ref readOnly, ref AddToRecent, Visible: ref Visible); 

docZero.Final = false; 
docZero.TrackRevisions = true; 
docZero.ShowRevisions = true; 
docZero.PrintRevisions = true; 

//the OfficeWord.WdCompareTargetNew defines a new file, you can change this valid value to change how word will open the document 
docZero.Compare(fileToCompare, missing, OfficeWord.WdCompareTarget.wdCompareTargetNew, true, false, false, false, false); 
+1

¡Hola @ anderson-rissardi! ¿Qué hace realmente el método Compare? ¿Abre algún archivo en alguna parte? Porque no veo nada cuando ejecuto esto en mi prueba de unidad. ¿Cómo se supone que obtendré el resultado ya que el método devuelve vacío? – ditoslav

+1

Hola @ditoslav. Abre un nuevo archivo. Es el botón 'Copare' dentro de la Palabra. Abra MS Word -> Tab 'Revisar' -> Botón 'Comparar'. Es la misma funcionalidad, se genera un nuevo documento. Debe hacer un save de este documento nuevo. –

0

Para hacer una comparación entre los documentos de Word, necesita

  1. Una biblioteca para manipular documento de Word, por ejemplo, leer párrafos, texto, tablas, etc. de un archivo de Word. Puede probar Office Interop, OpenXML o Aspose.Words for .NET.
  2. Algoritmo/biblioteca para hacer la comparación real, en el texto recuperado de ambos documentos de Word. Puede escribir el suyo o utilizar una biblioteca como DiffMatchPatch o similar.

Esta pregunta es antigua, ahora hay más soluciones disponibles, como GroupDocs Compare.

Document Comparison by Aspose.Words for .NET es un proyecto de escaparate de código abierto que utiliza Aspose.Words y DiffMatchPatch para comparar.

Trabajo en Aspose como Developer Evangelist.

1

Así que mis requisitos eran que tenía que usar una .Net lib y quería evitar trabajar en archivos reales pero trabajar con transmisiones.

ZipArchive está en System.IO.Compressed

Lo que hice y funcionó bastante bien estaba usando el ZipArchive de .Net y la comparación de contenidos, mientras que saltarse el archivo .rels porque parece que la que se genera aleatoriamente en cada creación de archivo. Aquí está mi fragmento:

private static bool AreWordFilesSame(byte[] wordA, byte[] wordB) 
    { 
     using (var streamA = new MemoryStream(wordA)) 
     using (var streamB = new MemoryStream(wordB)) 
     using (var zipA = new ZipArchive(streamA)) 
     using (var zipB = new ZipArchive(streamB)) 
     { 
      streamA.Seek(0, SeekOrigin.Begin); 
      streamB.Seek(0, SeekOrigin.Begin); 

      for(int i = 0; i < zipA.Entries.Count; ++i) 
      { 
       Assert.AreEqual(zipA.Entries[i].Name, zipB.Entries[i].Name); 

       if (zipA.Entries[i].Name.EndsWith(".rels")) //These are some weird word files with autogenerated hashes 
       { 
        continue; 
       } 

       var streamFromA = zipA.Entries[i].Open(); 
       var streamFromB = zipB.Entries[i].Open(); 

       using (var readerA = new StreamReader(streamFromA)) 
       using (var readerB = new StreamReader(streamFromB)) 
       { 
        var bytesA = readerA.ReadToEnd(); 
        var bytesB = readerB.ReadToEnd(); 
        if (bytesA != bytesB || bytesA.Length == 0) 
        { 
         return false; 
        } 
       } 
      } 

      return true; 
     } 
    } 
0

Para una solución en un servidor, o correr sin una instalación de la Palabra y el uso de las herramientas COM, se puede utilizar el componente de WmlComparer XmlPowerTools.

El documentation es un poco limitado, pero aquí es un ejemplo de uso:

var expected = File.ReadAllBytes(@"c:\expected.docx"); 
var actual = File.ReadAllBytes(@"c:\result.docx"); 
var expectedresult = new WmlDocument("expected.docx", expected); 
var actualDocument = new WmlDocument("result.docx", actual); 
var comparisonSettings = new WmlComparerSettings(); 

var comparisonResults = WmlComparer.Compare(expectedresult, actualDocument, comparisonSettings); 
var revisions = WmlComparer.GetRevisions(comparisonResults, comparisonSettings); 

que le mostrará las diferencias entre los dos documentos.

Cuestiones relacionadas