一、引言
建立完善的題庫是課程建設的一項重要工作,當數據庫的形式進行題庫管理,通過編寫抽題程序,在分類明確、題量豐富的題庫支持下,實現自動組卷並非難事。試卷一般都采用Word文檔,若采用VBA編程,要用程序將試題寫入到Word文檔,可以通過引用 Microsoft Word 9.0 Object Library中的相關對象來實現:圖片、圖形、文本框及藝術字等可利用Shapes集合對象的相應方法加入到文檔中;表格也可以通過Tables集合對象的Add 方法加入,其大小、位置等排版信息都可以以參數的形式傳入;而文字部分的內容也能以字符串的形式通過調用Content對象的InsertAfter方法插入,排版時對其字型、字體、字號及段落格式則可以利用Font對象及Paragraph對象的屬性或方式進行設置。
選擇題是各類試卷中經常出現的題型,而它的排版有其特殊性,因為選擇題的四個選項根據其長度有可能排成四段(行),也可能排成兩行,每行兩個選項,且它對段落縮進及上、下行中選項的對齊等都有一定的要求。一份美觀的試卷中選擇題的格式如圖1所示。
圖1 選擇題的排版效果
這裡要解決的幾個問題是:
1.題干部分的題號對齊,尤其是一位數題號與兩位數題號(如第9題與第10題);前、後題題干內容的第一個字符對齊;題干部分作為段落要采用懸掛縮進、且縮進量應合適。
2.若選項由四段(行)構成,則每段應有左縮進、縮進量與題干部分的懸掛縮進量相同,同時,選項內容的長度也有可以超過一行(如第10題中的選項C),所以對選項也要設置懸掛縮進、且縮進量應合適。
3.若選項由兩行構成(如第11題中的四個選項),則上一行的選項C與下一行的選項D應對齊。
二、定義選擇題的數據結構
程序設計中為了便於將選擇題作為函數的參數傳遞,應定義選擇題的數據類型的結構,選擇題的結構通常由題干及四個選項構成,具體定義如下:
Public Type Choice
Sentence As String '題干內容,不包括題號
ChoiceA As String '選項A的內容
ChoiceB As String '選項B的內容
ChoiceC As String '選項C的內容
ChoiceD As String '選項D的內容
End Type
三、頁面設置與段落格式
首先進行頁面設置,頁面上邊距、下邊距、左邊距、右邊距分別設為1英寸、1英寸、1.25英寸、1.25英寸, 默認制表位長度為0.33英寸。
With ActiveDocument.PageSetup
.TopMargin = InchesToPoints(1)
.BottomMargin = InchesToPoints(1)
.LeftMargin = InchesToPoints(1.25)
.RightMargin = InchesToPoints(1.25)
End With
ActiveDocument.DefaultTabStop = InchesToPoints(0.33)
為了對題干部分進行排版,先自定義一個過程insTabIndent,其功能是根據第一個參數str1傳入的題干內容及第二個參數Num傳入的本題題號,在題干內容前加上題號,若Num為0,則表示不加題號;在題號後設置一個制表位,使前、後題的題干內容的第一個字符對齊;對題干所在段落設置懸掛縮進一個制表。
Private Sub insTabIndent(str1 As String, Num As Integer)
Dim s As String
If Num < 10 Then s = " " + Trim(str(Num)) + "." Else s = Trim(str(Num)) + "."
If Num = 0 Then s = ""
Set myRange = appObj.ActiveDocument.Content
myRange.Collapse Direction:=wdCollapseEnd
myRange.InsertAfter s & vbTab & str1
myRange.InsertParagraphAfter
myRange.Font.Name = "宋體"
myRange.Font.Size = 12
myRange.ParagraphFormat.TabHangingIndent 1 '懸掛縮進1個制表位
End Sub
為了對選項進行排版,自定義一個過程insLeftAndHangingIndent,其功能是根據參數str1傳入的選項內容,將其作為段落寫入Word文檔,設置字型、字體、字號及左縮進和懸掛縮進。
Private Sub insLeftAndHangingIndent(str1 As String)
Set myRange = ActiveDocument.Content
myRange.Collapse Direction:=wdCollapseEnd
myRange.InsertAfter str1
myRange.InsertParagraphAfter
myRange.Font.Name = "宋體"
myRange.Font.Size = 12 '小四
'設置左縮進與懸掛縮進
myRange.ParagraphFormat.FirstLineIndent = CentimetersToPoints(-0.64)
myRange.ParagraphFormat.LeftIndent = CentimetersToPoints(1.48)
End Sub
四、選擇題的寫入及排版
如果四個選項按四段(行)進行排版,則只要通過調用前面所定義的兩個過程就能實現,但四個選項要按兩行排版則有兩種方法可供選擇:一是分節分欄法:將四個選項按四段寫入Word文檔,並將它們設置成單獨的一節,再采用分成兩欄的方法實現;二是直接寫入排版法:在同一行的兩個選項之間插入若干個制表位實現對齊,編程中將涉及寫入點的定位問題。
1、分節分欄法
選擇題寫入Word文檔及排版操作在自定義過程insSelect中實現,傳入參數mObj內封裝了一道選擇題;題號通過參數n傳入;參數max傳入的值是選項內容字符數的臨界值,即當四個選項內容中字符數最多者如果超過了max,則四個選項排版成四段(行),否則排成兩行。其中用到的函數maxLen(mObj)返回值表示選擇題mObj的四個選項內容中字符數的最大值。
Private Sub insSelect(mObj As Choice, ByRef n As Integer, max As Integer)
insTabIndent mObj.Sentence, n '寫入題干內容及題號
If maxLen(mObj) > max Then '按四段(行)並采用左縮進及懸掛縮進寫入
insLeftAndHangingIndent "A) " + mObj.ChoiceA
insLeftAndHangingIndent "B) " + mObj.ChoiceB
insLeftAndHangingIndent "C) " + mObj.ChoiceC
insLeftAndHangingIndent "D) " + mObj.ChoiceD
ActiveDocument.Content.InsertParagraphAfter
n = n + 1
Else '選項按縮進一個制表位形式寫入,為後面的分節分欄做准備
Set tempRange = ActiveDocument.Content
tempRange.Collapse Direction:=wdCollapseEnd
tempRange.InsertAfter vbTab & "A) " & mObj.ChoiceA
tempRange.InsertParagraphAfter
tempRange.InsertAfter vbTab & "B) " & mObj.ChoiceB
tempRange.InsertParagraphAfter
tempRange.InsertAfter vbTab & "C) " & mObj.ChoiceC
tempRange.InsertParagraphAfter
tempRange.InsertAfter vbTab & "D) " & mObj.ChoiceD
tempRange.InsertParagraphAfter
tempRange.Font.Name = "宋體"
tempRange.Font.Size = 12 '小四
n = n + 1 '題號增1,為寫入下一題做准備
tempRange.Select '選定四個選項所在的區域
If ActiveWindow.View.SplitSpecial <> wdPaneNone Then
ActiveWindow.Panes(2).Close
End If
If ActiveWindow.ActivePane.View.Type <> wdPrintView Then
ActiveWindow.ActivePane.View.Type = wdPrintView
End If
'在選定區域的起始位置和末尾位置插入分節符
ActiveDocument.Range(Start:=Selection.Start, End:=Selection.Start)._
InsertBreak Type:=wdSectionBreakContinuous
Selection.Start = Selection.Start + 1
ActiveDocument.Range(Start:=Selection.End, _
End:=Selection.End).InsertBreak Type:=wdSectionBreakContinuous '將選定的文本分成兩欄
With Selection.PageSetup.TextColumns
.SetCount NumColumns:=2
.EvenlySpaced = True
.LineBetween = False
.Width = CentimetersToPoints(6.95)
.Spacing = CentimetersToPoints(0)
End With
ActiveDocument.Content.InsertParagraphAfter
End If
End Sub
2、直接插入排版法
這種方法是將選項A與選項C作為同一行寫入、選項B與選項D作為同一行寫入,關鍵在於要求上一行的C選項與下一行的D選項要求對齊,定位方法是在選項A的末尾與選項C、選項B的末尾與選項D之間插入若干個制表位,模擬手工調整的方法進行對齊。但上、下行要分別插入多少個制表位才能對齊呢?這要借助於Selection對象的Information屬性進行檢測。Selection.Information(wdHorizontalPositionRelativeToPage)可以返回指定的所選內容或區域的水平位置,該位置是所選內容或區域的左邊與頁面的左邊之間的距離,以磅為單位(72磅 = 1英寸)。具體方法是每插入一個制表位就將選定區域收縮為選定區域後一個字符,同時檢測它距頁面的左邊之間的距離,直到距離達到某個設定值時就停止插入。具體程序如下:
insTabIndent "A) " + mObj.ChoiceA, 0 '寫入選項A
x = appObj.ActiveDocument.Content.Paragraphs.Count – 1
'x記錄下選項A所在的段落數
'每次循環插入一個制表位,並在循環條件中進行位置檢測
Do
Set tempRange = appObj.ActiveDocument.Range(appObj.ActiveDocument.Content.Paragraphs(x)._
Range.End - 1, appObj.ActiveDocument.Content.Paragraphs(x).Range.End)
tempRange.Select
Selection.TypeText vbTab '在選項A的內容後插入一個制表位
Set tempRange = appObj.ActiveDocument.Range(appObj.ActiveDocument.Content.Paragraphs(x)._
Range.End - 1, appObj.ActiveDocument.Content.Paragraphs(x).Range.End)
tempRange.Select '選定區域設為當前區域的最後位置
Loop While (Selection.Information(wdHorizontalPositionRelativeToPage) < 280)
'當檢測到寫入點位置距與頁面左邊的距離超過280磅時停止插入制表位
Selection.TypeText "C) " + mObj.ChoiceC '寫入選項C
'以下處理下一行的選項B和選項D,方法同上
insTabIndent "B) " + mObj.ChoiceB, 0 '寫入選項B
x = appObj.ActiveDocument.Content.Paragraphs.Count - 1
Do
Set tempRange = appObj.ActiveDocument.Range(appObj.ActiveDocument.Content.Paragraphs(x)._
Range.End - 1, appObj.ActiveDocument.Content.Paragraphs(x).Range.End)
tempRange.Select
Selection.TypeText vbTab
Set tempRange = appObj.ActiveDocument.Range(appObj.ActiveDocument.Content.Paragraphs(x)._
Range.End - 1, appObj.ActiveDocument.Content.Paragraphs(x).Range.End)
tempRange.Select
Loop While (Selection.Information(wdHorizontalPositionRelativeToPage) < 280)
Selection.TypeText "D) " + mObj.ChoiceD '寫入選項D
appObj.ActiveDocument.Content.InsertParagraphAfter
五、結語
前述兩種選擇題的排版方式均已在實際的試卷自動生成系統的排版應用中進行實測,測試表明兩種方法都能得到較為規范、美觀的排版效果。分節分欄法實現思想較為簡單,但由於生成的文檔中有大量的分節符,如果對於生成的文檔要作手工調整,可能會帶來一點麻煩;直接插入排版法的好處是不分節,便於後期的手工調整,但生成文檔的速度稍慢。
參考文獻
1.Microsoft Word 2000 Visual Basic 對象模型幫助系統[DK]
2.孟祥瑞.Visual Basic 6.0程序設計[M].華東理工大學出版社,2005