以编程方式比较word文档

问题描述:

我需要比较两个office文档,在这里是两个word文档,并提供一个区别,它与SVN中显示的有些类似。不是那样,但至少能够突出差异。以编程方式比较word文档

我试着用办公室COM DLL并走到这一步..

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); 

就如何进一步进行任何提示吗?这将是一个有很多命中的Web应用程序。正在使用办公室COM对象的正确方式,还是有任何其他的事情我可以看看?

+0

感兴趣的是,SVN如何显示两个二进制文件之间的差异? (AFAIK'docx'是一个zip档案格式) – sll

+0

选择有问题的两个文件,通常在客户端的同一文件夹中。你已经安装了tortoiseSVN。你右键点击并进入TortoiseSVN菜单并选择Diff ... – user20358

+0

是的,我知道如何做到这一点,但你会看到哪些区别,它有什么意义吗? – sll

我同意约瑟夫关于区分字符串。我还会推荐一个专用的差异引擎(在这里找到几个引擎:Any decent text diff/merge engine for .NET?),这可以帮助您避免差异中的一些常见缺陷。

你应该真的把文档解压缩成一个字符串并区分它。

您只关心文本更改而不关注格式化权限?

+1

的一切,即使图像不同。但我会尽量放松这个要求。 – user20358

您应该使用Document类来比较文件并在Word文档中打开结果。

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

Hi @ anderson-rissardi!比较方法实际上做了什么?它是否在某处打开某个文件?因为我在单元测试中运行时没有看到任何东西。我该如何得到结果,因为该方法返回无效? – ditoslav

+1

Hi @ditoslav。它会打开一个新文件。这是Word中的'Copare'按钮。打开MS Word - > Tab'Review' - > Button'Compare'。是相同的功能,它生成的新文档。您必须保存这个新文档。 –

要做到Word文档之间的比较,你需要

  1. 库来操纵Word文档,例如从Word文件中读取段落,文本,表格等。您可以尝试Office Interop,OpenXML或Aspose.Words for .NET
  2. 用于对从两个Word文档检索到的文本进行实际比较的算法/库。您可以自己编写或使用像DiffMatchPatch或类似的库。

这个问题很旧,现在有更多的解决方案,如GroupDocs Compare可用。

Document Comparison by Aspose.Words for .NET是一个开源展示项目,使用Aspose.Words和DiffMatchPatch进行比较。

我在Aspose作为开发者传播者工作。

所以我的要求是,我不得不使用.Net库,我想避免在实际文件上工作,但使用流。

ZipArchive是System.IO.Compressed

我做了什么,它的工作很好地使用从.NET中ZipArchive和比较的内容,同时跳过的.rels文件,因为它似乎是随机生成的每个文件的创建。这里是我的片断:

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; 
     } 
    } 

对于服务器上的解决方案,或者没有Word的安装运行和使用COM的工具,你可以使用的XmlPowerTools的WmlComparer组件。

documentation是有点有限的,但这里有一个例子用法:

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); 

它会告诉你这两个文件之间的差异。