كيف يمكنني استخدام جافا سكريبت داخل ماكرو Excel?
-
21-08-2019 - |
سؤال
هناك حقا بارد فرق الدرجة استضافته جوجل هنا:
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 الوظيفة الإضافية.