Reputation: 33
I wrote translation code. It generates buttons from our internal company dictionary (English on the left, Japanese on the right) that match search results for the selected text. I am using a shortcut key and running it each time I want to replace a new word with its translation.
I think where it can be improved is in the "Find" function in the Excel sheet.
Also, is it better to leave the translation sheet open the whole time or have it open and close each time it's used?
The spreadsheet contains about 10000 words and phrases, so it is pretty large, and will be used by multiple people at once.
Sub TranslationsOnRightClick()
''''Displays Translations From Right Click for a Selection in the Menu Bar.
' Recommended to map to a quick-key'''''''''''''''''''''''''
Dim oBtn As CommandBarButton
Dim oCtr As CommandBarControl
Dim Current As String
Dim oSheet As Excel.Range
Dim firstAddress As String
Dim oExcel As Excel.Application
Dim sFname As String
Dim oChanges As Excel.Workbook
Dim c As Excel.Range
Dim FoundTextEng As String
Dim FoundTextJap As String
On Error GoTo ErrorHandler
Set oExcel = New Excel.Application
oExcel.Visible = False
''''Insert Source Table Location Below''''''''''''''''''''''''''''''''''''''''''
sFname = "C:\Users\User\Desktop\translations.xlsx"
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Set oChanges = oExcel.Workbooks.Open(FileName:=sFname)
Set oSheet = oChanges.ActiveSheet.UsedRange
'Prepping Excel File
For Each oCtr In Application.CommandBars("Text").Controls
If Not oCtr.BuiltIn Then
oCtr.Delete
End If
Next oCtr
'Clear buttons from previous selection
Current = Selection
With oSheet
Set c = .Find(Current)
If Not c Is Nothing Then
firstAddress = c.Address
Do
Set oBtn = Application.CommandBars("Text").Controls.Add(msoControlButton, , , 1)
FoundTextEng = oChanges.ActiveSheet.Cells(c.Row, 1).Value
FoundTextJap = oChanges.ActiveSheet.Cells(c.Row, 2).Value
With oBtn
.Caption = FoundTextEng + " | " + FoundTextJap
.Style = msoButtonCaption
.Tag = FoundTextJap
.OnAction = "NewMacros.TranslationButton"
End With
Set c = .FindNext(c)
Loop While Not c Is Nothing And c.Address <> firstAddress
End If
End With
ErrorHandler:
oChanges.Close SaveChanges:=wdDoNotSaveChanges
oExcel.Quit
Exit Sub
lbl_Exit:
oChanges.Close SaveChanges:=wdDoNotSaveChanges
oExcel.Quit
Exit Sub
oChanges.Close SaveChanges:=wdDoNotSaveChanges
oExcel.Quit
End Sub
Sub TranslationButton()
''''Inserts Selected Text From Clicking Button Not to be Run Alone''''
Dim cbCtrl As CommandBarControl
Set cbCtrl = CommandBars.ActionControl
Options.ReplaceSelection = True
Selection.TypeText (cbCtrl.Tag)
End Sub
Upvotes: 2
Views: 435
Reputation:
I thought that the translator was a pretty interesting concept, so I wrote my own.
In my version the delimited data is stored in a global array. A second array is filled with all possible matches using the VBA Filter method. Next the options are numbered are loaded into an InputBox. The user enters the word or phrase into the ActiveCell, runs the macro, inputs the option number and the ActiveCell is translated. If the ActiveCell value is English it is translated to Japanese and if it is Japanese it is translated into English.
'Source Data: http://www.langage.com/vocabulaire/learn_japanese.htm
Public JapaneseTranslationArray() As String
Public Const Delimeter As String = " | "
Public Const APPNAME As String = "Japanese Translator"
Sub ShowTranslations()
Dim StartTime
Dim MacthString As String, msg As String
Dim isInitialized As Boolean
Dim x As Long
Dim arrData, result, index
On Error Resume Next
isInitialized = UBound(JapaneseTranslationArray) > -1
On Error GoTo 0
If Not isInitialized Then InitiateJapaneseTranslationArray
MacthString = Trim(ActiveCell.Value)
arrData = Filter(JapaneseTranslationArray, MacthString, True, vbTextCompare)
If UBound(arrData) = -1 Then
MsgBox "No Matches Found", vbInformation, APPNAME
Else
For x = 0 To UBound(arrData)
msg = msg & vbNewLine & (x + 1) & ". " & arrData(x)
Next
End If
index = InputBox(msg, APPNAME)
If IsNumeric(index) Then
result = arrData(index - 1)
If InStr(result, MacthString) > InStr(result, Delimeter) Then
ActiveCell.Value = Trim(Split(result, Delimeter)(0))
Else
ActiveCell.Value = Trim(Split(result, Delimeter)(1))
End If
End If
End Sub
Sub InitiateJapaneseTranslationArray()
Const TRANSLATIONS_PATH As String = "C:\Users\User\Desktop\translations.xlsx"
Dim oExcel As Excel.Application
Dim rData As Range
Dim FilePath As String
Dim oChanges As Excel.Workbook
Dim x As Long
Dim arrData
If Len(Dir(TRANSLATIONS_PATH)) = 0 Then
MsgBox "Translations File Not Found", vbCritical, APPNAME
Exit Sub
End If
On Error GoTo ErrorHandler
Set oExcel = New Excel.Application
Set oChanges = oExcel.Workbooks.Open(Filename:=TRANSLATIONS_PATH)
With oChanges.ActiveSheet
Set rData = oExcel.Intersect(.Columns("A:B"), .UsedRange)
If rData Is Nothing Then
MsgBox "No Data Found", vbCritical, APPNAME
GoTo ErrorHandler
Else
If rData.Columns.Count < 2 Then
MsgBox "No Data Found", vbCritical, APPNAME
GoTo ErrorHandler
Else
arrData = rData.Value
End If
End If
End With
ReDim JapaneseTranslationArray(UBound(arrData) - 1)
For x = 1 To UBound(arrData)
JapaneseTranslationArray(x - 1) = arrData(x, 1) & Delimeter & arrData(x, 2)
Next
isInitialized = True
ErrorHandler:
oChanges.Close SaveChanges:=False
oExcel.Quit
End Sub
Update:
Creating a new instance of Excel, opening the translations.xlsx, transferring the data into a public array and cleaning up was taking 2.24 seconds. I dump the array into a text file and see how long it would take to load the array. The VBA Timer which measures fractions of a second said that it took 0 seconds to load the array from a text file.
Here is the code using a translations.txt as the datasource. It is so fast I don't even use a global array. I just reload it every time.
Sub ShowTranslations2()
Const Delimeter As String = " | "
Const APPNAME As String = "Japanese Translator"
Const TRANSLATIONS_PATH As String = "C:\Users\best buy\Downloads\stackoverfow\translations.txt"
Dim MacthString As String, msg As String
Dim x As Long
Dim arrDictionary() As String
Dim arrData, result, index
On Error GoTo ErrHandler
If Len(Dir(TRANSLATIONS_PATH)) = 0 Then
MsgBox "Translations File Not Found", vbCritical, APPNAME
Exit Sub
End If
Open TRANSLATIONS_PATH For Input As #1
Do Until EOF(1)
ReDim Preserve arrDictionary(x)
Line Input #1, arrDictionary(x)
x = x + 1
Loop
Close #1
MacthString = Trim(ActiveCell.Value)
arrData = Filter(arrDictionary, MacthString, True, vbTextCompare)
If UBound(arrData) = -1 Then
MsgBox "No Matches Found", vbInformation, APPNAME
Else
For x = 0 To UBound(arrData)
msg = msg & vbNewLine & (x + 1) & ". " & arrData(x)
Next
End If
index = InputBox(msg, APPNAME)
If IsNumeric(index) Then
result = arrData(index - 1)
If InStr(result, MacthString) > InStr(result, Delimeter) Then
ActiveCell.Value = Trim(Split(result, Delimeter)(0))
Else
ActiveCell.Value = Trim(Split(result, Delimeter)(1))
End If
End If
Exit Sub
ErrHandler:
MsgBox "Oops Something Went Wrong", vbInformation, APPNAME
End Sub
I dumped the array into a text file use this code:
Sub PrintArray()
Const TRANSLATIONS_PATH As String = "C:\Users\best buy\Downloads\stackoverfow\translations.txt"
Open TRANSLATIONS_PATH For Output As #1
Write #1, Join(JapaneseTranslationArray, vbCrLf)
Close #1
End Sub
Upvotes: 2