王 超
(遼寧省交通規劃設計院有限責任公司公路養護技術研發中心 沈陽市 110111)
針對當前遼寧省安全監測系統中,依靠人工做成月度報告存在的效率低、容易出錯的問題,提出一套highcharts結合phantomjs的技術方案,開發了遼寧省高速公路橋梁安全監測系統月度報告生成系統,解決了需要通過前端網頁請求才能生成安全監測月度數據統計圖片,使安全監測月度報告通過程序自動生成,提高了報告做成的效率,對安全監測系統的推廣應用提供了保障。
多年來,橋梁結構的安全狀況一直是公眾特別關心的問題。橋梁結構在服役期間,不可避免地要受到自然環境(大氣腐蝕、溫濕度變化、地震、風)和使用環境(荷載作用頻率增加、材料與結構的疲勞)的影響,必然會逐漸產生損壞現象,進而導致自身結構性能降低,可能導致橋梁發生倒塌等事故;在橋梁上安裝安全監測系統,是指利用現場安裝的且對結構安全無損的傳感器元件,對橋梁結構進行長期的在線監測,實時地監控橋梁結構的運營狀態,并做成月度報告和年度報告對橋梁上所有傳感器的變化趨勢進行展示和分析,及時客觀地評價橋梁結構的狀況,進一步提高橋梁的運營安全性。
在安裝安全監測系統時,會在橋梁的不同位置上安裝很多傳感器,如圖1所示。

圖1 安全監測系統傳感器布置圖
做橋梁安全監測月度報告的時候,需要技術人員登錄橋梁安全監測管理系統,手動查詢每個傳感器的月度的數據變化圖,并且收集每個月傳感器典型日的特定時間的數據,做成對比表格,將傳感器變化圖和數據對比表格添加到Word中。隨著安裝安全監測系統的橋梁數量越來越多,人工做成安全監測月度報告效率低,容易出錯的缺陷越來越突出,如何提高安全監測月度報告的做成效率成為亟待考慮和解決的問題。
MicoSoft Word提供的強大的編程接口技術使得我們利用編程工具通過程序對Word進行控制,自動添加數據生成報告成為了可能:添加COM引用,將word的類庫DLL組件導入到C#.net中,在源代碼中引入相應的命名空間,這樣就可以調用各種Word的操作函數。
生成橋梁安全監測月度報告的時候,主程序首先需要創建一個空白的Word文檔,將模板中的內容拷貝到空白Word文檔中,模板通過書簽規定了不同類型傳感器數據在Word中的放置位置,根據用戶選擇的橋梁,連接部署該橋梁安全監測系統的下位機,從下位機中取得所有傳感器的月度數據,利用phantomjs[1],將傳感器的月度數據生成統計圖片,再利用Word類庫組件中的操作函數[2],將統計圖片插入到文檔對應位置中,然后再將傳感器典型日的特定時間的數據,利用Word類庫組件中的操作函數,做成對比表格插入到Wrod文檔中,完成后,將安全監測報告保存到服務器端以便用戶下載使用,系統處理流程如圖2所示。

圖2 安全監測報告生成流程
以上便是安全監測報告生成的主要邏輯框架,在下一節中將具體說明主要部分的實現方法。
根據系統設計,生成橋梁安全監測月度報告主要包含了如下的幾個操作:創建打開Word空白文檔,拷貝模板數據[3];通過定位書簽位置確定月度數據統計圖需要插入的Word中的位置;取得傳感器月度數據,生成統計圖,插入到Word中;插入典型日的對比數據表格;關閉及下載安全監測報告,下面分別介紹這些操作的實現方法。
創建、獲取一個Word文檔對象是對Word操作的基礎,再生成Wrod報告的時候,需要首先在內存中創建一個Word文檔對象,關鍵的調用函數如下:
using MsWord =Microsoft.Office.Interop.Word;
MsWord.Application WordApp = new MsWord.ApplicationClass();
使用Word文檔對象,創建一個Word文檔,關鍵的調用函數如下:
MsWord.Document WordDoc = WordApp.Documents.Add(missing, missing, missing, missing);
將監測報告模板中的內容拷貝到新建的Wrod文檔中,并打開Word文檔,關鍵的調用函數如下:
File.Copy(TemplateFile, FileName);
WordDoc = WordApp.Documents.Open(Obj_FileName, missing, ReadOnly, missing);
WordDoc.Activate();
程序使用了Word的標簽將不同傳感器數據插入到檢測報告不同的位置,向監測報告模板中添加標簽的方法:將光標定位在監測報告文檔相應的位置,然后選擇Word菜單中的“插入”->“書簽”,定義書簽名,點擊“添加”按鈕,書簽添加成功,這里需要注意,“書簽名”是書簽的唯一標識,不允許重復。
定位書簽位置的時候,首先需要取得書簽名,即首先確定當前的數據或者圖片需要添加在監測報告的位置,調用Word文檔對象定位書簽位置,關鍵的調用函數:
object BookMarkName = strBookMarkName;
WordDoc.ActiveWindow.Selection.GoTo(ref what, ref missing, ref missing, ref BookMarkName);
安全監測系統中使用highcharts插件進行圖表展示[4],人工做成安全監測月度報告時,通過操作安全監測系統中的按鈕來向后臺發起請求,后臺獲取到圖片的SVG信息時,生成對應的圖片,也就是說圖片生成必須依賴前端來觸發。
自動生成安全監測報告時,沒有系統前端,如果通過模擬前端自動向后臺發送請求,效率非常的差。經過充分的調研,系統通過引入phantomjs來解決這個問題,它是個javascript引擎庫,基于webkit內核,能解析前臺的HTML及javascript并生成對應的圖片,而且能夠以服務的形式獨立運行在后端,不需要前端觸發。
調用phantomjs的關鍵函數如下:
Process p = new Process();
p.StartInfo.FileName=System.AppDomain.CurrentDomain.BaseDirectory+"jsphantomjs.exe";
string ExcuteArg = System.AppDomain.CurrentDomain.BaseDirectory + "jshighcharts-convert.js-infile " + infile + "-outfile " + outfile + "-scale 2.5-width 300-constr Chart";
p.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
infile是輸入圖片的參數,是json文件,將json的路徑傳入,phantomjs會根據 highcharts-convert.js 去解析json文件生成圖片,json模板文本格式比較常見,由于篇幅限制不再列出。
首先連接部署該橋梁安全監測系統的下位機,從下位機中取得傳感器的月度數據,替換json模板文件中的數據,以溫度傳感器SCT001為例,統計數據圖中的橫坐標為時間,需要將時間按如下格式′(1-1)0:00:00′添加到json模板文件的xAxis-> categories標簽中,該傳感器的采集頻率為1min,下一條數據為′(1-1)0:01:00′,依次類推,以“,”分割數據;統計數據圖中的縱坐標為溫度,取得橫坐標所有時刻對應的溫度數據,添加到json模板文件的series-> data標簽中,在更新完橫坐標和縱坐標的數據后,還需要取得縱坐標中所有溫度數據的最大值和最小值,加權后,添加到json模板文件的gridLineDashStyle-> max/min標簽中,如何不設置這個內容,會因為圖中顯示的最大值/最小值過大,導致統計數據是一條橫線,看不出變化趨勢。
做成json文件后,調用phantomjs.exe 傳入圖片生成的路徑、json文件,即可在指定的路徑下,生成如圖3所示的圖片:

圖3 傳感器月度數據統計圖
接下來,取得要插入統計數據圖片位置的書簽名,調用Word文檔對象將生成的圖片插入到對應位置,調用的關鍵函數:
WordDoc.Application.ActiveDocument.InlineShapes.AddPicture(outfile, ref LinkToFile, ref SaveWithDocument, ref Anchor);
生成月度圖片添加到Word文檔中的詳細處理流程如圖4所示。

圖4 生成圖片流程圖
需要說明的是:將WebService部署到IIS上時,IIS上通常運行的賬戶是“NetWork Service”,權限比較小,使用賬戶“NetWrok Service”無法正常啟動phantomjs.exe進程生成統計數據圖片,所以需要將IIS程序池中運行賬戶修改為管理員。修改IIS程序池中運行賬戶的方法:打開IIS,選擇你要更改的應用程序池,右鍵選擇“高級設置”,“標識”,“自定義賬戶”,“設置”,輸入本機中有管理員權限的用戶即可。
向Word中插入文字的方法比較簡單,調用Word文檔對象TypeText函數即可,調用的關鍵函數如下:
WordDoc.ActiveWindow.Selection.TypeText(reader["PictureName"].ToString());
向Word中插入一個二維表格,其形式如表1所示:

表1 典型時刻數據統計表格
首先根據表格的行數和列數,在文檔的光標位置插入一個二維表格,調用的關鍵函數如下所示:
Microsoft.Office.Interop.Word.Table newTable = WordDoc.Tables.Add(WordApp.Selection.Range, iRowCount, iColumnCount, ref missing, ref missing);
創建表格后,循環遍歷每一行,對當前行中各個列的數據設置內容,調用的關鍵函數如下所示:
for(int iLoop = StartRowIndex + 1; iLoop <= iRowCount; iLoop++)
{
newTable.Cell(iLoop, 1).Range.Text =(iCurrentMonth).ToString()+ "月";
newTable.Cell(iLoop, 2).Range.Text = strSensorName;
newTable.Cell(iLoop, 3).Range.Text = listFittingContainer2.First().Value.YValue;
}
在對單元格合并的時候,記錄開始單元格位置和結束單元格位置,直接進行合并,則會將從開始單元格位置到結束單元格位置的所有單元格合并成一個單元格,關鍵函數如下:
newTable.Cell(1, 1).Merge(newTable.Cell(1, 3));
在報告做成之后,需要關閉Word文檔,關鍵的調用函數:
WordDoc.Close(ref missing, ref missing, ref missing);
WordApp.Quit(ref missing, ref missing, ref missing);
然后將Word保存在服務器的指定位置,用戶在使用的時候,需要下載到本地,下載Word文檔的關鍵的調用函數:
FileInfo fileInfo = new FileInfo(FileName);
Response.WriteFile(fileInfo.FullName);
Response.Flush();
本文列舉的所有程序使用Visual Studio 2010和Micosoft word2007調試通過。
利用C#.net開發工具可以高效地操作Word文檔,為自動生成專業格式的Word報告提供了可能,本文利用highcharts結合phantomjs,以服務的形式獨立運行在后端,不需要前端觸發即可生成傳感器的月度數據統計圖片,然后利用C#.net對Word的控制技術,向Word報告中插入傳感器數據統計圖片和變化統計表格,自動生成遼寧省公路橋梁安全監測月度報告。解決了人工做成橋梁安全監測月度報告效率低,容易出錯的問題,為安全監測系統的推廣應用提供了有效的保障。