若您開發的程式為多國人員使用,相信一定會有此需求,但Office 2003這個古老的產品,要如何生出多與界面呢?它沒有現代化的開發工具可供快速套用,但我們可以試著使用VBA來解決這個需求,因為只要能控制每個物件的外觀,就能達到使用者界面的多語需求。
我們於需要多語界面的表單上,建立一個名為「Combo_lng」的下拉方塊,並且貼上以下程式:
於該表單的Form_Load加上以下程式碼
Private Sub Form_Load()
Combo_lng.RowSource = "SELECT DISTINCT A.Lang " & vbCrLf & _
"FROM UI_Localization AS A " & vbCrLf & _
"WHERE (((A.Form)='" & Me.Name & "')) "
Combo_lng.Value = Config(Me.Name & ".Lang")
If Combo_lng.Value <> "" Then
combo_lng_AfterUpdate
End If
End Sub
貼上以下三個Combo_lng用的事件模組
Private Sub combo_lng_AfterUpdate()
If IsNull(Combo_lng) Then Exit Sub
Call UIData_Put(Me.Name, Combo_lng)
End Sub
Private Sub Combo_lng_DblClick(Cancel As Integer)
Dim i As Integer
Dim bnForceUpdate As Boolean
If IsNull(Combo_lng.Value) Or Len(Combo_lng.Value) = 0 Then Exit Sub
If MsgBox("是否強制更新?如果有新增物件請強制更新!", vbOKCancel) = vbOK Then
bnForceUpdate = True
Else
bnForceUpdate = False
End If
Call UIData_Get(Me.Name, Combo_lng.Value, bnForceUpdate)
Combo_lng.Requery
End Sub
Private Sub Combo_lng_KeyDown(KeyCode As Integer, Shift As Integer)
On Error Resume Next
If KeyCode = 13 Then
Dim strSQL As String
Dim i As Integer
If MsgBox("是否開啟此語系的資料進行編輯?", vbOKCancel) = vbOK Then
If ifObjectExists("UI_Localization") = False Then
If MsgBox("資料表不存在,是否建立資料表,並且將" & Combo_lng.text & "語系存入?", vbOKCancel) = vbOK Then
Call UIData_Get(Me.Name, Combo_lng.text)
Else
Exit Sub
End If
Else
i = DCount("Lang", "UI_Localization", "Form='" & Me.Name & "' AND Lang='" & Combo_lng.text & "'")
If i = 0 Then
If MsgBox("" & Combo_lng.text & "語系資料不存在,是否要產生?", vbOKCancel) = vbOK Then
Call UIData_Get(Me.Name, Combo_lng.text)
Else
Exit Sub
End If
End If
End If
strSQL = "SELECT * FROM UI_Localization WHERE Form='" & Me.Name & "' AND Lang='" & Combo_lng.text & "'"
Call OpenTempQuery("UI", strSQL, acEdit)
ElseIf MsgBox("是否強制更新" & Combo_lng.text & "介面?", vbOKCancel) = vbOK Then
Call UIData_Get(Me.Name, Combo_lng.text, True)
ElseIf MsgBox("是否僅帶入" & Combo_lng.text & "語言資料,而不變動位置?", vbOKCancel) = vbOK Then
Call UIData_Put(Me.Name, Combo_lng.text, True)
Combo_lng.text = ""
Combo_lng.Value = ""
End If
Combo_lng.SetFocus
Combo_lng.Requery
End If
End Sub
然後於三個事件重新建立連結,以便之後使用
以下兩個程式碼請複製到Public模組內,這兩個是用來存取物件狀態的程式
此程式用來讀取各物件的屬性,並將屬性值儲存於資料庫中,並依照使用者的語言類型分類
Function UIData_Get(strFormName As String, strLang As String, Optional bnForceUpdate As Boolean = False)
If strFormName = "" Or strLang = "" Then Exit Function
If ifObjectExists("UI_Localization") = False Then
'http://allenbrowne.com/ser-49.html
'Access可用欄位類型:TEXT (size),CHAR (size),MEMO,BYTE,SHORT,LONG,SINGLE,DOUBLE,GUID,DECIMAL (precision, scale)
' DATETIME,CURRENCY,COUNTER (seed, increment),YESNO,LONGBINARY,BINARY (size)
DoCmd.RunSQL "CREATE TABLE UI_Localization " & _
"(" & _
" [Form] Text(50), " & _
" [Lang] Text(3), " & _
" [Name] Text(50), " & _
" [ControlType] Text(3), " & _
" [Value] YESNO, " & _
" [Caption] Text(255), " & _
" [Left] Text(50), " & _
" [Top] Text(50), " & _
" [Width] Text(50), " & _
" [Height] Text(50), " & _
" [Vertial] Text(50), " & _
" [FontName] Text(50), " & _
" [FontSize] Text(50), " & _
" [TextAlign] Text(50), " & _
" [ControlTipText] Text(50), " & _
" [Disabled] YESNO " & _
")"
End If
Dim objCtl As Object
Dim i As Integer
Dim m As Object
Dim strObjCtlValue As String
'確認之前是否有該語系資料存在
i = DCount("Lang", "UI_Localization", "Form='" & strFormName & "' AND Lang='" & strLang & "'")
'若為強制更新,先刪除資料再將i歸零
If i > 0 And bnForceUpdate = True Then
If MsgBox("請注意!即將強制更新資料!!語系:" & strLang, vbOKCancel) <> vbOK Then Exit Function
RunSQL "DELETE * FROM UI_Localization WHERE Form='" & strFormName & "' AND Lang='" & strLang & "'"
i = 0
End If
If i > 0 Then
'有原有資料的話, 更新資料
If MsgBox("請注意!即將覆蓋資料!!語系:" & strLang, vbOKCancel) <> vbOK Then Exit Function
'依照ControlType特性更新資料
For Each objCtl In Forms(strFormName).Controls
If objCtl.ControlType = 100 Then 'Label
Set m = CurrentDb.OpenRecordset("SELECT * FROM UI_Localization WHERE Name ='" & objCtl.Name & "' AND Form = '" & strFormName & "' AND Lang='" & strLang & "' AND Disabled = False")
If m.EOF = False Then
m.Edit
m("Left") = objCtl.Left
m("Top") = objCtl.Top
m("Width") = objCtl.Width
m("Height") = objCtl.Height
m("FontName") = objCtl.FontName
m("FontSize") = objCtl.FontSize
m("TextAlign") = objCtl.TextAlign 'v
m("Caption") = objCtl.Caption
m("ControlTipText") = objCtl.ControlTipText
m("ControlType") = objCtl.ControlType
m.Update
End If
ElseIf objCtl.ControlType = 104 Then 'Command
Set m = CurrentDb.OpenRecordset("SELECT * FROM UI_Localization WHERE Name ='" & objCtl.Name & "' AND Form = '" & strFormName & "' AND Lang='" & strLang & "' AND Disabled = False")
If m.EOF = False Then
m.Edit
m("Left") = objCtl.Left
m("Top") = objCtl.Top
m("Width") = objCtl.Width
m("Height") = objCtl.Height
m("FontName") = objCtl.FontName
m("FontSize") = objCtl.FontSize
m("Caption") = objCtl.Caption
m("ControlTipText") = objCtl.ControlTipText
m("ControlType") = objCtl.ControlType
m.Update
End If
ElseIf objCtl.ControlType = 122 Then 'Toggle
If IsNull(objCtl.Value) Then
strObjCtlValue = False
Else
strObjCtlValue = objCtl.Value
End If
Set m = CurrentDb.OpenRecordset("SELECT * FROM UI_Localization WHERE Name ='" & objCtl.Name & "' AND Form = '" & strFormName & "' AND Lang='" & strLang & "' AND Value=" & strObjCtlValue & " AND Disabled = False")
If m.EOF = False Then
m.Edit
m("Left") = objCtl.Left
m("Top") = objCtl.Top
m("Width") = objCtl.Width
m("Height") = objCtl.Height
m("FontName") = objCtl.FontName
m("FontSize") = objCtl.FontSize
m("Caption") = objCtl.Caption
m("ControlTipText") = objCtl.ControlTipText
m("ControlType") = objCtl.ControlType
m.Update
End If
End If
Next objCtl
Else
'沒有的話,寫入資料
For Each objCtl In Forms(strFormName).Controls
'依照ControlType特性寫入
If objCtl.ControlType = 100 Then 'Label
Set m = CurrentDb.OpenRecordset("SELECT * FROM UI_Localization ")
m.AddNew
m("Name") = objCtl.Name
m("Form") = strFormName
m("Lang") = strLang
m("Disabled") = False
m("Left") = objCtl.Left
m("Top") = objCtl.Top
m("Width") = objCtl.Width
m("Height") = objCtl.Height
m("FontName") = objCtl.FontName
m("FontSize") = objCtl.FontSize
m("TextAlign") = objCtl.TextAlign 'v
m("Caption") = objCtl.Caption
m("ControlTipText") = objCtl.ControlTipText
m("ControlType") = objCtl.ControlType
m.Update
ElseIf objCtl.ControlType = 104 Then 'Command
Set m = CurrentDb.OpenRecordset("SELECT * FROM UI_Localization ")
m.AddNew
m("Name") = objCtl.Name
m("Form") = strFormName
m("Lang") = strLang
m("Disabled") = False
m("Left") = objCtl.Left
m("Top") = objCtl.Top
m("Width") = objCtl.Width
m("Height") = objCtl.Height
m("FontName") = objCtl.FontName
m("FontSize") = objCtl.FontSize
m("Caption") = objCtl.Caption
m("ControlTipText") = objCtl.ControlTipText
m("ControlType") = objCtl.ControlType
m.Update
ElseIf objCtl.ControlType = 122 Then 'Toggle
If IsNull(objCtl.Value) Then
strObjCtlValue = False
Else
strObjCtlValue = objCtl.Value
End If
Set m = CurrentDb.OpenRecordset("SELECT * FROM UI_Localization ")
m.AddNew
m("Name") = objCtl.Name
m("Form") = strFormName
m("Lang") = strLang
m("Value") = strObjCtlValue
m("Disabled") = False
m("Left") = objCtl.Left
m("Top") = objCtl.Top
m("Width") = objCtl.Width
m("Height") = objCtl.Height
m("FontName") = objCtl.FontName
m("FontSize") = objCtl.FontSize
m("Caption") = objCtl.Caption
m("ControlTipText") = objCtl.ControlTipText
m("ControlType") = objCtl.ControlType
m.Update
ElseIf objCtl.ControlType = 124 Then 'Toggle
Set m = CurrentDb.OpenRecordset("SELECT * FROM UI_Localization ")
m.AddNew
m("Name") = objCtl.Name
m("Form") = strFormName
m("Lang") = strLang
m("Value") = strObjCtlValue
m("Disabled") = False
m("Left") = objCtl.Left
m("Top") = objCtl.Top
m("Width") = objCtl.Width
m("Height") = objCtl.Height
m("Caption") = objCtl.Caption
m("ControlTipText") = objCtl.ControlTipText
m("ControlType") = objCtl.ControlType
m.Update
Else
Debug.Print objCtl.ControlType & " " & objCtl.Name
End If
Next objCtl
End If
MsgBox "完成!"
End Function
將物件設定由資料庫取出,放到物件上使用:
Function UIData_Put(strFormName As String, strLang As String, Optional bnOnlyLang As Boolean = False)
Dim m As Object
Dim strName As String
If strLang = "" Then Exit Function
If ifObjectExists("UI_Localization") = False Then Exit Function
Dim objCtl As Object
'確認是否有該語言存在
Set m = CurrentDb.OpenRecordset("SELECT * FROM UI_Localization WHERE Form = '" & strFormName & "' AND Lang='" & strLang & "' And Disabled = False")
If m.EOF = True Then
MsgBox "無此語言資料!"
Exit Function
End If
strName = m("Name")
'有的話將找出的資料寫入Form中
Do
If m("ControlType") = 100 Then
Set objCtl = Forms(strFormName).Controls(m("Name"))
If bnOnlyLang = False Then
objCtl.Left = m("Left")
objCtl.Top = m("Top")
objCtl.Width = m("Width")
objCtl.Height = m("Height")
End If
objCtl.FontName = m("FontName")
objCtl.FontSize = m("FontSize")
objCtl.TextAlign = m("TextAlign")
If IsNull(m("Caption")) = False Then objCtl.Caption = m("Caption")
If IsNull(m("ControlTipText")) = False Then objCtl.ControlTipText = m("ControlTipText")
ElseIf m("ControlType") = 104 Then
Set objCtl = Forms(strFormName).Controls(m("Name"))
If bnOnlyLang = False Then
objCtl.Left = m("Left")
objCtl.Top = m("Top")
objCtl.Width = m("Width")
objCtl.Height = m("Height")
End If
objCtl.FontName = m("FontName")
objCtl.FontSize = m("FontSize")
If IsNull(m("Caption")) = False Then objCtl.Caption = m("Caption")
If IsNull(m("ControlTipText")) = False Then objCtl.ControlTipText = m("ControlTipText")
ElseIf m("ControlType") = 122 Then
Set objCtl = Forms(strFormName).Controls(m("Name"))
If bnOnlyLang = False Then
objCtl.Left = m("Left")
objCtl.Top = m("Top")
objCtl.Width = m("Width")
objCtl.Height = m("Height")
End If
objCtl.FontName = m("FontName")
objCtl.FontSize = m("FontSize")
If objCtl.Value = m("Value") Or IsNull(objCtl.Value) Then
If IsNull(m("Caption")) = False Then objCtl.Caption = m("Caption")
If IsNull(m("ControlTipText")) = False Then objCtl.ControlTipText = m("ControlTipText")
End If
ElseIf m("ControlType") = 124 Then
Set objCtl = Forms(strFormName).Controls(m("Name"))
If bnOnlyLang = False Then
objCtl.Left = m("Left")
objCtl.Top = m("Top")
objCtl.Width = m("Width")
objCtl.Height = m("Height")
End If
If IsNull(m("Caption")) = False Then objCtl.Caption = m("Caption")
If IsNull(m("ControlTipText")) = False Then objCtl.ControlTipText = m("ControlTipText")
End If
m.MoveNext
Loop Until m.EOF = True
Call ConfigSave(strFormName & ".Lang", strLang)
End Function
我們這裡建立一個名為「F_Day10」的表單進行示範,裡面塞了Access的各式物件
我們於新增的「Combo_lng」下拉方塊物件上手動輸入三碼語言碼,我的資料表設計為僅儲存三碼當作語言分類,如果需要更多碼的,可以再自行調整,三碼輸入完後,按下Enter
之後會出現「是否開啟此語系的資料進行編輯?」,我們這裡選擇是
如果初次使用,將會詢問是否建立資料表,並儲存語系資料,這裡選擇是
完成視窗,按下確定
隨後會帶出剛剛建立的該語言物件清單,這裡我們由於是建立CHT(繁體),所以這裡就暫時不改
將資料表關閉後,可以由下拉選單看到CHT的語言可選
我們再依照上面的順序,建立ENG英文語言
最後開啟ENG語言清單,我們將Caption的部份進行修改
然後語言的部份下拉到ENG並選擇
接下來就會看到,修改的部份都顯示出來了,但「子表單」的部份就沒有改到了
修改語言的部份,有個很大的問題是,不同語言的空間使用有所不同,所以會需要再調整物件的位置與大小,但是該如何調整?有幾個步驟需要處理,首先要把語言內容翻譯完成,這樣才能知道佔用的空間差異,若還沒修改好,可點選「Combo_lng」物件輸入文字的部份,然後按下Enter,即可依照之前步驟修改翻譯內容。
待完成後,我們要接著修改物件位置與大小,這時候各位會想到,那就轉到「設計模式」即可,但沒這麼簡單,如果直接轉設計模式
你會發現各物件的Caption都還停留在未更改的狀態
我們再切到檢視畫面
於檢視畫面中的任何物件上按下滑鼠右鍵->屬性
修改任何屬性的內容,然後再改回原始值
然後回到表單畫面,按下「存檔」
儲存完畢後,再切到「設計檢視」即可看到以改為英文狀態
然後我們再依照自己的需求,修改字型大小、字體,調整位置,然後存檔,關閉此表單
然後切到資料表上,會看到已建立了「UI_Localization」資料表,但我們不是要開這個,而是開「Config」
我們將 F_Day10.Lang的資料刪除掉(Delete)
按是進行刪除
這裡是為了讓開啟表單時,不要執行載入上一個選擇的語言設定,進行刪除後,找不到上一筆語言設定即可
然後我們手動輸入ENG然後按Enter
編輯選擇取消
強制更新,選擇確定
按確定後更新
完成後按確定
然後語言下拉選單切換,就可以看到效果
但由於我的程式沒有針對Font Color(字體顏色)與Font Bold(粗體字)的設定進行存取,因此切回CHT時,這兩個屬性還是留著
以上程式與資料表設定並非完美,僅為個人開發使用,若有需求者,可以再依照自己的需求加以改善。今日的分享,希望各位喜歡!