FarPoint Spread 是功能強大的類 Excel 表格控件,廣泛應用於 WinForms 應用。但官方文檔多以 VB6/VB.NET 為主,C# 開發者在引用、資料綁定、單元格操作上常遇「坑」。本文整理實戰經驗,涵蓋控件載入、DataSet 轉換、兩種高效填充方案,助你避開彎路。
提示:若先裝 VS 再裝 Spread,可能自動註冊;反之則需手動添加。載入較慢屬正常,耐心等待。
Spread 6.0 雖兼容 C#,但非為 C# 設計。資料綁定、事件模型、屬性命名均遵循 VB 風格,C# 下開發體驗明顯不如 VB.NET 順暢。除非客戶強制要求,新專案建議優先考慮原生 DataGridView 或第三方 C# 優先控件(如 DevExpress, Syncfusion)。
Spread 習慣處理「二維表格」資料(類 VB Recordset),而 ADO.NET DataSet 內部以 XML 結構儲存多張表:
<NewDataSet>
<authors>
<au_id>172-32-1176</au_id>
<au_lname>White</au_lname>
...
</authors>
<authors1> ... </authors1> <!-- 第二張表 -->
</NewDataSet>
每張表對應一個 XML 標籤(<authors>),每行記錄為子元素,欄位值為孫元素。Spread 無法直接識別此結構,必須轉換為其可接受的格式(剪貼板文本:Tab 分欄、換行分行)。
適用於資料量中等、需逐格驗證或格式化的場景。
// 設定 Spread 尺寸
axvSpread1.MaxRows = ds.Tables[tableName].Rows.Count;
axvSpread1.MaxCols = ds.Tables[tableName].Columns.Count;
axvSpread1.Row = 1; axvSpread1.Col = 1;
axvSpread1.Row2 = axvSpread1.MaxRows;
axvSpread1.Col2 = axvSpread1.MaxCols;
// 逐格填入
for (int i = 1; i <= ds.Tables[tableName].Rows.Count; i++)
{
for (int j = 1; j <= ds.Tables[tableName].Columns.Count; j++)
{
axvSpread1.Row = i;
axvSpread1.Col = j;
axvSpread1.Value = ds.Tables[tableName].Rows[i-1][j-1].ToString();
}
}
優點:邏輯清晰,易於在賦值前做型別轉換、格式化、驗證。
缺點:大數據量(萬行以上)時較慢,COM 互操作開銷大。
利用 Spread Clip 屬性接受「Tab/換行分隔文本」的特性,將 DataSet XML 一次性轉為純文本灌入。
// 1. 設定尺寸(同方案一)
axvSpread1.MaxRows = ds.Tables[tableName].Rows.Count;
axvSpread1.MaxCols = ds.Tables[tableName].Columns.Count;
axvSpread1.Row = 1; axvSpread1.Col = 1;
axvSpread1.Row2 = axvSpread1.MaxRows;
axvSpread1.Col2 = axvSpread1.MaxCols;
// 2. 取得 XML 並正則轉換
string xmlStr = ds.GetXml();
// 移除無意義空白
xmlStr = Regex.Replace(xmlStr, @"[\n\r\v\t]*", "");
// 移除 NewDataSet 標籤
xmlStr = Regex.Replace(xmlStr, @"\<(|/)NewDataSet\>", "");
// 移除所有起始標籤 <tag>
xmlStr = Regex.Replace(xmlStr, @"\<([^/]*)\>", "");
// 目標表的結束標籤 </authors> 替換為換行 \r
string endTag = @"\</" + tableName + @"\>";
xmlStr = Regex.Replace(xmlStr, endTag, "\r");
// 其他結束標籤 </field> 替換為 Tab \t
xmlStr = Regex.Replace(xmlStr, @"\</[\w]*\>", "\t");
// 3. 一次性寫入
axvSpread1.Clip = xmlStr;
核心邏輯:保留「值」與「結構分隔符」,丟棄所有 XML 標籤。
優點:極快,適合大數據量。
缺點:正則較脆弱,表名含特殊字符需轉義;無法在寫入過程中逐格處理。
若專案大量使用 Spread,可封裝一個 FakeRecordset 類,內部用 object[,] 或 List<object[]> 模擬 VB Recordset 結構,提供 GetClipString() 輸出標準格式。實現 IEnumerable 並配合擴展方法,可實現 spread.LoadFrom(recordset) 風格 API,一勞永逸。
| 方案 | 適用場景 | 性能 | 靈活度 |
|---|---|---|---|
| 雙層迴圈 | 中小數據、需逐格邏輯 | 中 | 高 |
| XML+Regex+Clip | 大數據、純顯示、結構固定 | 高 | 低 |
| 自定義兼容層 | 長期專案、多處複用 | 高 | 最高 |
再次強調:新專案慎用 Spread 6.0。若必須維護舊系統,掌握上述兩招足以應對 90% 場景。核心心法:「抓住老鼠就是好貓」,只要能把 DataSet 變成 Spread 能吃的格式,手段不拘。