2013-09-30 15 views
6

wahrscheinlich könnte eine seltene Petition sein, aber hier ist das Problem.Übersetzen Sie Text mit VBA

Ich passe ein Excel von einem Drittanbieter an meine Organisation an. Das Excel ist in Englisch entwickelt und die Leute meiner Organisation sprechen nur Spanisch. Ich möchte genau den gleichen Code verwenden, den das ursprüngliche Arbeitsblatt hat, ich bevorzuge es nicht zu berühren (obwohl ich es tun kann), also möchte ich eine Funktion verwenden, die jedes Mal, wenn eine msgbox erscheint (mit dem Text in Englisch) , Übersetze ich die msgbox-Nachrichten, aber ohne das ursprüngliche Skript zu berühren. Ich suche nach einer Maske, die jedes Mal aufgerufen werden kann, wenn eine msgbox im ursprünglichen Code aufgerufen wird.

Ich bevorzuge nicht den ursprünglichen Code zu berühren, weil der Fremdentwickler es häufig ändern könnte, und es könnte sehr ärgerlich sein, den Code jedes Mal zu ändern, wenn sie eine kleine Änderung vornehmen.

Ist das möglich?

+6

ja, es ist möglich. –

Antwort

15

Hier gehen Sie.

Sub test() 
    Dim s As String 
    s = "hello world" 
    MsgBox transalte_using_vba(s) 

End Sub 


Function transalte_using_vba(str) As String 
' Tools Refrence Select Microsoft internet Control 


    Dim IE As Object, i As Long 
    Dim inputstring As String, outputstring As String, text_to_convert As String, result_data As String, CLEAN_DATA 

    Set IE = CreateObject("InternetExplorer.application") 
    ' TO CHOOSE INPUT LANGUAGE 

    inputstring = "auto" 

    ' TO CHOOSE OUTPUT LANGUAGE 

    outputstring = "es" 

    text_to_convert = str 

    'open website 

    IE.Visible = False 
    IE.navigate "http://translate.google.com/#" & inputstring & "/" & outputstring & "/" & text_to_convert 

    Do Until IE.ReadyState = 4 
     DoEvents 
    Loop 

    Application.Wait (Now + TimeValue("0:00:5")) 

    Do Until IE.ReadyState = 4 
     DoEvents 
    Loop 

    CLEAN_DATA = Split(Application.WorksheetFunction.Substitute(IE.Document.getElementById("result_box").innerHTML, "</SPAN>", ""), "<") 

    For j = LBound(CLEAN_DATA) To UBound(CLEAN_DATA) 
     result_data = result_data & Right(CLEAN_DATA(j), Len(CLEAN_DATA(j)) - InStr(CLEAN_DATA(j), ">")) 
    Next 


    IE.Quit 
    transalte_using_vba = result_data 


End Function 
+3

+1 langsam, aber effektiv :) –

+0

Danke für diese Antwort sehr hilfreich für die Übersetzung. Zusätzlich möchte ich eine Funktion haben, die jedes Mal, wenn eine msgbox aufgerufen wird, diese translate-Funktion aufruft. – MariPlaza

+0

@ user1827572 msgbox war zu Demonstrationszwecken. Sie können diesen Wert in eine Zeichenfolge aufnehmen und verwenden. – Santosh

0

Update:For Each v In arr_Response Verbesserte -iteration, spezielle charactors ermöglicht. Mauszeigeränderung hinzugefügt, wenn die Übersetzung verarbeitet wird. Ein Beispiel hinzugefügt, wie der übersetzte output_string verbessert werden kann.

Es gibt einen Großteil der freien Übersetzung API outthere, aber keiner scheint Googles Translation Service, GTS zu schlagen (meiner Meinung nach). Als Folge der Beschränkungen von Googles auf die kostenlose GTS-Nutzung scheint der beste VBA-Ansatz auf die IE.navigation beschränkt zu sein - wie auch Santoshs Antwort betont.

Mit diesem Ansatz verursacht einige Probleme. Der IE-instans weiß nicht, wann die Seite vollständig geladen ist, und IE.ReadyState ist wirklich nicht vertrauenswürdig. Daher muss der Coder "Delays" mit der Funktion Application.Wait hinzufügen. Wenn Sie diese Funktion verwenden, erraten Sie nur, wie lange es dauert, bis die Seite vollständig geladen ist. In Situationen, in denen das Internet wirklich langsam ist, könnte diese fest codierte Zeit nicht ausreichen. Der folgende Code behebt das mit dem ImprovedReadyState.

In Situationen, in denen ein Blatt unterschiedliche Spalten hat und Sie in jede Zelle eine andere Übersetzung hinzufügen möchten, finde ich den besten Ansatz, wo die Übersetzungszeichenfolge dem ClipBoard zugewiesen wird, anstatt eine VBA-Funktion innerhalb der Formel. Dadurch können Sie die Übersetzung einfach einfügen und als String ändern.

Columns in Excel

Wie verwenden:

  1. Legen Sie die Verfahren in eine benutzerdefinierten VBA-Modul
  2. ändern Sie die 4 Const Ihren Wunsch der (siehe oberen TranslationText)
  3. eines Vergeben Kurzschlussschlüssel zum Auslösen des TranslationText -Verfahrens

Shortkey Excel

  1. Aktivieren Sie die Zelle, die Sie übersetzen möchten. Die erste Zeile muss mit einem Language-Tag enden.Etc. "_da", "_en", "_de". Wenn Sie eine andere Funktionalität wollen, ändern Sie ws_ActiveWS.Cells(r_ActiveCell.Row, r_InputRange.Column)

enter image description here

  1. Drücken Sie die Tastenkürzel von 4. (usw. CTRL + SHIRT + S). Siehe Prozess in Ihrer Prozessleiste (unten in Excel). Einfügen (STRG + V), wenn Übersetzung durchgeführt wird angezeigt:

enter image description here Translation done

Option Explicit 

    'Description: Translates content, and put the translation into ClipBoard 
    'Required References: MIS (Microsoft Internet Control) 
    Sub TranslateText() 

    'Change Const's to your desire 
    Const INPUT_RANGE As String = "table_products[productname_da]" 
    Const INPUT_LANG As String = "da" 
    Const PROCESSBAR_INIT_TEXT As String = "Processing translation. Please wait... " 
    Const PROCESSBAR_DONE_TEXT As String = "Translation done. " 

    Dim ws_ActiveWS As Worksheet 
    Dim r_ActiveCell As Range, r_InputRange As Range 
    Dim s_InputStr As String, s_InputLang As String, s_OutputLang As String, arr_Response() As String, s_Translation As String 
    Dim o_IE As Object, o_MSForms_DataObject As Object 
    Dim i As Long 
    Dim v As Variant 

    Set o_MSForms_DataObject = CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}") 
    Set ws_ActiveWS = ThisWorkbook.ActiveSheet 
    Set r_ActiveCell = ActiveCell 
    Set o_IE = CreateObject("InternetExplorer.Application") 
    Set r_InputRange = ws_ActiveWS.Range(INPUT_RANGE) 

    'Update statusbar ("Processing translation"), and change cursor 
    Application.Statusbar = PROCESSBAR_INIT_TEXT 
    Application.Cursor = xlWait 

    'Declare inputstring (The string you want to translate from) 
    s_InputStr = ws_ActiveWS.Cells(r_ActiveCell.Row, r_InputRange.Column) 

    'Find the output-language 
    s_OutputLang = Right(ws_ActiveWS.Cells(1, r_ActiveCell.Column).Value, 2) 

    'Navigate to translate.google.com 
    With o_IE 

     .Visible = False 'Run IE in background 
     .Navigate "http://translate.google.com/#" & INPUT_LANG & "/" _ 
      & s_OutputLang & "/" & s_InputStr 

     'Call improved IE.ReadyState 
     Do 
      ImprovedReadyState 
     Loop Until Not .Busy 

     'Split the responseText from Google 
     arr_Response = Split(.Document.getElementById("result_box").innerHTML, "<span class") 

     'Remove html from response, and construct full-translation-string 
     For Each v In arr_Response 
      s_Translation = s_Translation & Replace(v, "<span>", "") 
      s_Translation = Replace(s_Translation, "</span>", "") 
      s_Translation = Replace(s_Translation, """", "") 
      s_Translation = Replace(s_Translation, "=hps>", "") 
      s_Translation = Replace(s_Translation, "=atn>", "") 
      s_Translation = Replace(s_Translation, "=hps atn>", "") 

      'Improve translation. 
      'This could etc. be moved to seperate sheets (containing every language), and make the lookup in a dynamic table/sheet. Futurely it'd be possible to hook on the changeevent, and automatically improve the translation-algoritmen. 
      'If Google can't translate the etc. the word "Lys", you can extend the translation, with an auto correction. This example shows to autocorrect the word "Lys" -> "ljus". 
      If (s_OutputLang = "sv") Then 
       s_Translation = Replace(s_Translation, "lys", "ljus") 
      End if 
     Next v 

     'Put Translation into Clipboard 
     o_MSForms_DataObject.SetText s_Translation 
     o_MSForms_DataObject.PutInClipboard 

     If (s_Translation <> vbNullString) Then 
      'Put Translation into Clipboard 
      o_MSForms_DataObject.SetText s_Translation 
      o_MSForms_DataObject.PutInClipboard 

      'Update statusbar ("Translation done"). If the input_string is above 70 chars (which is roughly the limitation in processbar), then cut the string, and extend with "...". 
      Application.Statusbar = PROCESSBAR_DONE_TEXT & """" & IIf(Len(s_InputStr) < 70, s_InputStr, Mid(s_InputStr, 1, 70) & "...") & """" 
     Else 
      'Update statusbar ("Error") 
      Application.Statusbar = PROCESSBAR_ERROR_TEXT 
     End If 

     'Cleanup 
     .Quit 

     'Change cursor back to default 
     Application.Cursor = xlDefault 

     Set o_MSForms_DataObject = Nothing 
     Set ws_ActiveWS = Nothing 
     Set r_ActiveCell = Nothing 
     Set o_IE = Nothing 

    End With 

End Sub 

Sub ImprovedReadyState() 

    Dim si_PauseTime As Single: si_PauseTime = 1 'Set duration 
    Dim si_Start As Single: si_Start = Timer 'Set start-time 
    Dim si_Finish As Single 'Set end-time 
    Dim si_TotalTime As Single 'Calculate total time. 

    Do While Timer < (si_Start + si_PauseTime) 
     DoEvents 
    Loop 

    si_Finish = Timer 

    si_TotalTime = (si_Finish - si_Start) 

End Sub 
0

Die Antwort von Unicco geschrieben ist groß!

Ich entfernte die Tabelle Zeug und machte es aus einer einzigen Zelle arbeiten, aber das Ergebnis ist das gleiche.

Mit etwas von dem Text, den ich übersetze (Operationsanweisungen in einem Herstellungskontext), fügt Google manchmal Mist zur Rückkehrzeichenkette hinzu, manchmal sogar die Antwort verdoppelend, unter Verwendung zusätzlicher < "span"> Konstrukte.

Ich habe die folgende Zeile in den Code direkt nach dem 'Next v':

s_Translation = RemoveSpan(s_Translation & "") 

und erstellt diese Funktion (in dem selben Modul):

Private Function RemoveSpan(Optional InputString As String = "") As String 

Dim sVal As String 
Dim iStart As Integer 
Dim iEnd As Integer 
Dim iC As Integer 
Dim iL As Integer 

If InputString = "" Then 
    RemoveSpan = "" 
    Exit Function 
End If 

sVal = InputString 

' Look for a "<span" 
iStart = InStr(1, sVal, "<span") 

Do While iStart > 0 ' there is a "<span" 
    iL = Len(sVal) 
    For iC = iStart + 5 To iL 
     If Mid(sVal, iC, 1) = ">" Then Exit For ' look for the first ">" following the "<span" 
    Next 
    If iC < iL Then ' then we found a "<" 
     If iStart > 1 Then ' the "<span" was not in the beginning of the string 
      sVal = Left(sVal, iStart - 1) & Right(sVal, iL - iC) ' grab to the left of the "<span" and to the right of the ">" 
     Else ' the "<span" was at the beginning 
      sVal = Right(sVal, iL - iC) ' grap to the right of the ">" 
     End If 
    End If 
    iStart = InStr(1, sVal, "<span") ' look for another "<span" 
Loop 
    RemoveSpan = sVal 
End Function 

Im Rückblick erkennen ich, Ich hätte das effizienter machen können, aber es funktioniert und ich ziehe weiter!

4

So würde ich es machen. Es ist eine Funktion mit optionalen Enumerationsobjekten, die auf die von Google Translate verwendeten Sprachcodes zeigen. Der Einfachheit halber habe ich nur ein paar Sprachcodes eingefügt. Außerdem habe ich in diesem Beispiel die Microsoft Internet Controls-Referenz ausgewählt, sodass anstelle eines Objekts ein InternetExplorer-Objekt verwendet wird. Und schließlich, um loszuwerden, die Ausgabe bereinigen zu müssen, habe ich nur .innerText statt .innerHTML verwendet. Denken Sie daran, dass es bei google translate ein Zeichenlimit von etwa 3000 oder so gibt, und Sie müssen IE = nichts setzen, wenn Sie dieses mehrfach verwenden, andernfalls werden Sie mehrere IE-Prozesse erstellen und es wird schließlich nicht funktionieren nicht mehr.

einrichten ...

Option Explicit 

Const langCode = ("auto,en,fr,es") 

Public Enum LanguageCode 
    InputAuto = 0 
    InputEnglish = 1 
    InputFrench = 2 
    InputSpanish = 3 
End Enum 

Public Enum LanguageCode2 
    ReturnEnglish = 1 
    ReturnFrench = 2 
    ReturnSpanish = 3 
End Enum 

-Test ...

Sub Test() 

Dim msg As String 

msg = "Hello World!" 

MsgBox AutoTranslate(msg, InputEnglish, ReturnSpanish) 

End Sub 

Funktion ...

Public Function AutoTranslate(ByVal Text As String, Optional LanguageFrom As LanguageCode, Optional LanguageTo As LanguageCode2) As String 

Dim langFrom As String, langTo As String, IE As InternetExplorer, URL As String, myArray 

If IsMissing(LanguageFrom) Then 
    LanguageFrom = InputAuto 
End If 
If IsMissing(LanguageTo) Then 
    LanguageTo = ReturnEnglish 
End If 

myArray = Split(langCode, ",") 
langFrom = myArray(LanguageFrom) 
langTo = myArray(LanguageTo) 

URL = "https://translate.google.com/#" & langFrom & "/" & langTo & "/" & Text 

Set IE = New InternetExplorer 

IE.Visible = False 
IE.Navigate URL 

    Do Until IE.ReadyState = 4 
     DoEvents 
    Loop 

    Application.Wait (Now + TimeValue("0:00:5")) 

    Do Until IE.ReadyState = 4 
     DoEvents 
    Loop 

    AutoTranslate = IE.Document.getElementByID("result_box").innerText 

    IE.Quit 

    Set IE = Nothing 


End Function 
1

Einer der modernen Lösung mit Google Translation API Google Aktivieren Übersetzungs-API, zuerst sollten Sie das Projekt und die Anmeldeinformationen erstellen. Wenn Sie 403 (Tageslimit) erhalten, müssen Sie in Ihrem Google Cloud-Konto eine Zahlungsmethode hinzufügen, um sofort Ergebnisse zu erhalten.

Private Function GoogleTranslateJ(ByVal text, ByVal resLang, ByVal srcLang) As String 
Dim jsonProvider As Object 

Dim jsonResult As Object 
Dim jsonResultText As String 

Dim googleApiUrl As String 
Dim googleApiKey As String 

Dim resultText As String 

Set jsonProvider = CreateObject("MSXML2.ServerXMLHTTP") 

text = Replace(text, " ", "%20") 
googleApiKey = "ijHF28h283fjijefiwjeofij90f2h923" 'YOUR GOOGLE API KEY 

googleApiUrl = "https://translation.googleapis.com/language/translate/v2?key=" & googleApiKey & "&source=" & srcLang & "&target=" & resLang & "&q=" & text 

jsonProvider.Open "POST", googleApiUrl, False 
jsonProvider.setRequestHeader "Content-type", "application/text" 
jsonProvider.send ("") 
jsonResultText = jsonProvider.responseText 

Set jsonResult = JsonConverter.ParseJson(jsonResultText) 
Set jsonResult = jsonResult("data") 
Set jsonResult = jsonResult("translations") 
Set jsonResult = jsonResult(1) 

resultText = jsonResult("translatedText") 

GoogleTranslateJ = resultText 
End Function 
Verwandte Themen