سؤال

هناك حقا بارد فرق الدرجة استضافته جوجل هنا:

http://code.google.com/p/google-diff-match-patch/

لقد استعملت من قبل في عدد قليل من المواقع على شبكة الإنترنت, ولكن الآن أنا بحاجة إلى استخدام هذا داخل ماكرو Excel مقارنة نصية بين خليتين.

بيد أنه لا تتوفر إلا في جافا سكريبت, Python, Java, C++, لا VBA.

يمكن للمستخدمين تقتصر على Excel 2003 حتى النقي .صافي الحل لن ينجح.ترجمة التعليمات البرمجية VBA يدويا سيستغرق الكثير من الوقت وجعل الترقية صعبة.

خيار واحد أنا نظرت إلى ترجمة جافا سكريبت أو المصدر Java باستخدام .صافي المجمعين (JScript.NET أو ي#), استخدام عاكس إلى الإخراج VB.NET ثم أخيرا بخفض VB.NET رمز يدويا إلى VBA ، إعطائي نقية VBA الحل.بعد أن مشاكل الحصول على ترجمة مع أي .صافي مترجم, أنا التخلي عن هذا المسار.

على افتراض كنت قد حصلت على العمل .صافي المكتبة, كان يمكن أن تستخدم أيضا ExcelDna (http://www.codeplex.com/exceldna) مفتوح المصدر Excel الوظيفة الإضافية لجعل .صافي رمز التكامل أسهل.

آخر فكرة استضافة إنترنت إكسبلورر كائن ، وإرساله جافا سكريبت المصدر ، واصفا إياه.حتى لو حصلت على هذا العمل, تخميني هو أنه سيكون من التراب-بطيئة وفوضوية.

تحديث:الحل موجود!

لقد استخدمت WSC الطريقة الموضحة أدناه قبل الجواب المقبول.اضطررت إلى تغيير WSC رمز قليلا لتنظيف ديفس و تعيد لي VBA متوافق مع مجموعة من المصفوفات:

function DiffFast(text1, text2)
{
    var d = dmp.diff_main(text1, text2, true);
    dmp.diff_cleanupSemantic(d);
    var dictionary = new ActiveXObject("Scripting.Dictionary"); // VBA-compatible array
    for ( var i = 0; i < d.length; i++ ) {
    dictionary.add(i, JS2VBArray(d[i]));
    }
    return dictionary.Items();
}

function JS2VBArray(objJSArray)
{
    var dictionary = new ActiveXObject("Scripting.Dictionary");
    for (var i = 0; i < objJSArray.length; i++) {
        dictionary.add( i, objJSArray[ i ] );
        }
    return dictionary.Items();
}

لقد سجلت WSC وانها عملت على ما يرام.الرمز في VBA تسميته كما يلي:

Public Function GetDiffs(ByVal s1 As String, ByVal s2 As String) As Variant()
    Dim objWMIService As Object
    Dim objDiff As Object
    Set objWMIService = GetObject("winmgmts:")
    Set objDiff = CreateObject("Google.DiffMatchPath.WSC")
    GetDiffs = objDiff.DiffFast(s1, s2)
    Set objDiff = Nothing
    Set objWMIService = Nothing
End Function

(حاولت الحفاظ على عالمية واحدة objWMIService و objDiff حولها حتى لا تضطر إلى إنشاء/تدمير هذه لكل خلية, ولكن لا يبدو أن تحدث فرقا في الأداء.)

ثم كتب الرئيسي الماكرو.يستغرق ثلاثة معايير:مجموعة (عمود واحد) من القيم الأصلية مجموعة من القيم ومجموعة حيث مهرجان دبي السينمائي الدولي يجب تفريغ النتائج.كلها يفترض أن يكون نفس العدد من الصف ليس لدي أي خطأ خطير-التحقق يحدث هنا.

Public Sub DiffAndFormat(ByRef OriginalRange As Range, ByRef NewRange As Range, ByRef DeltaRange As Range)
    Dim idiff As Long
    Dim thisDiff() As Variant
    Dim diffop As String
    Dim difftext As String
    difftext = ""
    Dim diffs() As Variant
    Dim OriginalValue As String
    Dim NewValue As String
    Dim DeltaCell As Range
    Dim row As Integer
    Dim CalcMode As Integer

هذه الثلاث المقبلة خطوط تسريع التحديث دون بإفساد المفضل للمستخدم حساب وضع في وقت لاحق:

    Application.ScreenUpdating = False
    CalcMode = Application.Calculation
    Application.Calculation = xlCalculationManual
    For row = 1 To OriginalRange.Rows.Count
        difftext = ""
        OriginalValue = OriginalRange.Cells(row, 1).Value
        NewValue = NewRange.Cells(row, 1).Value
        Set DeltaCell = DeltaRange.Cells(row, 1)
        If OriginalValue = "" And NewValue = "" Then

محو السابقة ديفس ، إن وجدت ، من المهم:

            Erase diffs

هذا الاختبار هو البصري اختصار المستخدمين لذلك فمن الواضح عندما لا يوجد تغيير على الإطلاق:

        ElseIf OriginalValue = NewValue Then
            difftext = "No change."
            Erase diffs
        Else

الجمع بين جميع النص معا الدلتا قيمة الخلية ، سواء كان النص متطابقة ، إدراجها أو حذفها:

            diffs = GetDiffs(OriginalValue, NewValue)
            For idiff = 0 To UBound(diffs)
                thisDiff = diffs(idiff)
                difftext = difftext & thisDiff(1)
            Next
        End If

يجب عليك تعيين قيمة قبل بدء التنسيق:

        DeltaCell.value2 = difftext
        Call FormatDiff(diffs, DeltaCell)
    Next
    Application.ScreenUpdating = True
    Application.Calculation = CalcMode
End Sub

هنا هو الرمز الذي يفسر ديفس و صيغ الدلتا الخلية:

Public Sub FormatDiff(ByRef diffs() As Variant, ByVal cell As Range)
    Dim idiff As Long
    Dim thisDiff() As Variant
    Dim diffop As String
    Dim difftext As String
    cell.Font.Strikethrough = False
    cell.Font.ColorIndex = 0
    cell.Font.Bold = False
    If Not diffs Then Exit Sub
    Dim lastlen As Long
    Dim thislen As Long
    lastlen = 1
    For idiff = 0 To UBound(diffs)
        thisDiff = diffs(idiff)
        diffop = thisDiff(0)
        thislen = Len(thisDiff(1))
        Select Case diffop
            Case -1
                cell.Characters(lastlen, thislen).Font.Strikethrough = True
                cell.Characters(lastlen, thislen).Font.ColorIndex = 16 ' Dark Gray http://www.microsoft.com/technet/scriptcenter/resources/officetips/mar05/tips0329.mspx
            Case 1
                cell.Characters(lastlen, thislen).Font.Bold = True
                cell.Characters(lastlen, thislen).Font.ColorIndex = 32 ' Blue
        End Select
        lastlen = lastlen + thislen
    Next
End Sub

هناك بعض الفرص الأمثل, ولكن حتى الآن أنها تعمل على ما يرام.شكرا لكل من ساعد!

هل كانت مفيدة؟

المحلول

أبسط النهج قد يكون تضمين جافا سكريبت مهرجان دبي السينمائي الدولي المنطق إلى مكون COM مباشرة باستخدام جافا سكريبت.وهذا ممكن عن طريق ما يسمى "مكونات البرنامج النصي Windows".

هنا البرنامج التعليمي على خلق WSCs.

Windows Script عنصر مكون COM التي تم تعريفها في البرنامج النصي.واجهة المكون عبر COM, مما يعني أنه هو VBA ودية.المنطق هو تنفيذها في أي Windows Scripting استضافة متوافق مع اللغة مثل JavaScript أو VBScript.WSC يتم تعريفها في ملف XML واحد ، مما يضمن المنطق ، عنصر معرف الفئة ، وأساليب التسجيل المنطق ، وهلم جرا.

هناك أيضا الأدوات المتاحة للمساعدة في خلق WSC.الاساس هو معالج من نوع الشيء الذي يسألك أسئلة و يملأ قالب XML.نفسي بدأت مع مثال على ذلك .wsc الملفات وتحريرها باليد مع محرر نص.انها جميلة النفس التفسيرية.

مكون COM تعريف هذه الطريقة في البرنامج النصي (في .wsc ملف) للاستدعاء مثل أي مكون COM, من أي بيئة يمكن أن الرقص مع COM.

التحديث:أخذت بضع دقائق أنتجت WSC على GoogleDiff.ومن هنا.

<?xml version="1.0"?>

<package>

<component id="Cheeso.Google.DiffMatchPatch">

  <comment>
    COM Wrapper on the Diff/Match/Patch logic published by Google at http://code.google.com/p/google-diff-match-patch/.
  </comment>

<?component error="true" debug="true"?>

<registration
  description="WSC Component for Google Diff/Match/Patch"
  progid="Cheeso.Google.DiffMatchPatch"
  version="1.00"
  classid="{36e400d0-32f7-4778-a521-2a5e1dd7d11c}"
  remotable="False">

  <script language="VBScript">
  <![CDATA[

    strComponent = "Cheeso's COM wrapper for Google Diff/Match/Patch"

    Function Register
      MsgBox strComponent & " - registered."
    End Function

    Function Unregister
      MsgBox strComponent & " - unregistered."
    End Function

  ]]>
  </script>
</registration>


<public>
  <method name="Diff">
    <parameter name="text1"/>
    <parameter name="text2"/>
  </method>
  <method name="DiffFast">
    <parameter name="text1"/>
    <parameter name="text2"/>
  </method>
</public>


<script language="Javascript">
<![CDATA[


    // insert original google diff code here...


// public methods on the component
var dpm = new diff_match_patch();


function Diff(text1, text2)
{
   return dpm.diff_main(text1, text2, false);
}


function DiffFast(text1, text2)
{
   return dpm.diff_main(text1, text2, true);
}


]]>
</script>

</component>

</package>

لاستخدام هذا الشيء, يجب عليك أن تسجل ذلك.في Explorer, انقر بزر الماوس الأيمن واختر "تسجيل".أو من سطر الأوامر:regsvr32 الملف:\c:\scripts\GoogleDiff.wsc

أنا لم أحاول استخدامه من VBA, ولكن هنا بعض التعليمات البرمجية VBScript يستخدم عنصر.

Sub TestDiff()
    dim t1 
    t1 = "The quick brown fox jumped over the lazy dog."

    dim t2 
    t2 = "The large fat elephant jumped over the cowering flea."

    WScript.echo("")

    WScript.echo("Instantiating a Diff Component ...")
    dim d
    set d = WScript.CreateObject("Cheeso.Google.DiffMatchPatch")

    WScript.echo("Doing the Diff...")
    x = d.Diff(t1, t2)

    WScript.echo("")
    WScript.echo("Result was of type: " & TypeName(x))
    ' result is all the diffs, joined by commas.  
    ' Each diff is an integer (position), and a string.  These are separated by commas.
    WScript.echo("Result : " & x)

    WScript.echo("Transform result...")
    z= Split(x, ",")
    WScript.echo("")
    redim diffs(ubound(z)/2)
    i = 0
    j = 0
    For Each item in z
      If (j = 0) then
        diffs(i) = item
        j = j+ 1      
      Else 
          diffs(i) = diffs(i) & "," & item
        i = i + 1
        j = 0
      End If
    Next

    WScript.echo("Results:")
    For Each item in diffs
      WScript.echo("  " & item)
    Next

    WScript.echo("Done.")

End Sub

نصائح أخرى

على Windows Scripting Engine سوف يسمح لك لتشغيل مكتبة جافا سكريبت.أنه يعمل بشكل جيد في تجربتي.

سيكون اقتراحي أن كل ما تفعله أنت ألفه في المجمع COM.VBA صفقات أفضل مع كائنات COM لذا أنت يمكن أن تجمع مثل .صافي مكون ثم كشف كائن COM باستخدام interop وظائف .صافي.

كبديل يمكنك أيضا أن ننظر إلى استخدام Windows Scripting Host الكائنات تنفيذ جافا سكريبت الملف و يمكنك العودة في النتيجة.

هنا خيار آخر للنظر ، على الرغم من أنني لست بأي وسيلة تفيد أفضل واحد.

  • التأكد من أن الثعبان النسخة يجمع في IronPython.(يجب أن لا يكون هناك أي مشاكل هنا أو فقط كمية صغيرة من ترقية على الأكثر.)
  • إنشاء Excel الوظيفة الإضافية في المكتبة باستخدام C# و مرجع IronPython من ذلك.
  • التفاف وظيفة ضرورية في C# Excel الوظيفة الإضافية.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top