C#實現(xiàn)格式化文本并導(dǎo)入到Excel
需求
在一些導(dǎo)入功能里,甲方經(jīng)常會給我們一些格式化的文本,類似 CSV 那樣的純文本。比如有關(guān)質(zhì)量監(jiān)督的標(biāo)準(zhǔn)文件(如國家標(biāo)準(zhǔn)、地方標(biāo)準(zhǔn)、企業(yè)標(biāo)準(zhǔn)等),還有一此國際標(biāo)準(zhǔn)文件等等。提供給我們的這些文件是文件尺寸比較大的純文本文件,文件內(nèi)容是格式化的文本,具有規(guī)律的分隔字符。Excel 本身提供有導(dǎo)入文本文件的功能,但由于標(biāo)準(zhǔn)制定和發(fā)布是比較頻繁,每次的導(dǎo)入與整理還是比較耗時的,因些實現(xiàn)文本文件導(dǎo)入到 Excel 的功能可以更快速的解決重復(fù)勞動和錯誤,實現(xiàn)流程自動化的一環(huán)。
Excel 的文本文件導(dǎo)入功能
我們運行 Excel ,點擊選擇打開文本文件時,會彈出一個導(dǎo)入向?qū)?,如下圖:
如圖我們需要選擇合適的文本文件原始編碼,輸入分隔符,選擇其它的選項,如連續(xù)的分隔符號視分單個處理等。下面我們將介紹如何利用 COM 來實現(xiàn)這一操作的自動化處理。
范例運行環(huán)境
操作系統(tǒng): Windows Server 2019 DataCenter
操作系統(tǒng)上安裝 Office Excel 2016
.net版本: .netFramework4.7.1 或以上
開發(fā)工具:VS2019 C#
配置Office DCOM
配置方法可參照我的文章《C# 讀取Word表格到DataSet》進(jìn)行處理和配置。
實現(xiàn)
組件庫引入
OpenTextToExcelFile
OpenTextToExcelFile方法返回 object[] 類型,object[0] 返回生成成功的 Excel 文件地址,object[1]返回錯誤信息,其實體為 string 類型。方法參數(shù)據(jù)說明見下表:
序號 | 參數(shù) | 類型 | 說明 |
---|---|---|---|
1 | OpenFile | string | 打開的文本文件的絕對完整路徑及名稱。 |
2 | ExcelFile | string | 要生成的Excel文件完整路徑地址。 |
3 | SplitChar | string | 分隔符 |
4 | ReplaceChars | string[,] | 這是一個導(dǎo)入后數(shù)據(jù)整理型參數(shù)。一個二維數(shù)組,用于導(dǎo)入后替換相關(guān)字符的數(shù)組,第一維為查找字符串 ,第二維為要替換的字符串。 |
5 | ValidResult | int | 這是一個檢驗型參數(shù)。指定有效的字段生成數(shù),如果小于1則不進(jìn)行判斷,否則如果生成的最終列數(shù)與此值不符,則生成錯誤信息以示警告。 |
6 | ExtraSplit | bool | 是否允許刪除指定的一系列列值。 |
7 | Esplits | int[] | 當(dāng)ExtraSplit為true時,些數(shù)據(jù)生效,如定義1、6、19列等。這些列的值將在Esplits參數(shù)數(shù)組中定義。Esplits數(shù)組的指定生效順序在StartCol參數(shù)之后 |
8 | AddCols | object[,] | 這是一個整理型參數(shù)。表示要添加幾個固定列及固定值,維度包括3列,如object[0,0] 存儲要寫入的列id,object[0,1] 存儲列id的標(biāo)題值,object[0,2] 存儲列id的值。示例如下: object[0,0]=10; object[0,1]="導(dǎo)入標(biāo)志"; object[0,2]="是"; |
9 | ref_maxcolid | int | 指定在打開文本文件之后應(yīng)該生成的最大的列,一般這個參數(shù)用于最后一列都為空的情況,因為這樣EXCEL無法定位最后一個單元格,如果為0則忽略 |
10 | StartCol | int | 這是一個整理型參數(shù)。指定額外的刪除列策略,默認(rèn)值為1,表示不處理,<=0 則表示刪除前幾列。即 Math.Abs(StartCol) 個,默認(rèn)步長為 1。 |
11 | offerset | int | 與StartCol參數(shù)配合,默認(rèn)值為1,表示刪除步長。注意:改變此值會影響刪除列的個數(shù)。 |
12 | origin | int | 文本文件的原始編碼,默認(rèn)為 65001,即UTF-8 |
13 | ConsecutiveDelimiter | bool | 如果為 true,則將連續(xù)分隔符視為一個分隔符,如“##” 則視為“#”。 默認(rèn)值為 false。 |
代碼
方法完整代碼如下:
/*本方法通過打開一個具有一定分隔格式的文本到EXCEL中,并且由EXCEL進(jìn)行整理 * openfile參數(shù):打開的文件絕對完整路徑及名稱。splitchar參數(shù):分隔符。ReplaceChars參數(shù):一個二維數(shù)組,用于整理后替換相關(guān)字符的數(shù)組,第一維為查找字符串 * ,第二維為要替換的字符串。allowtodataset參數(shù):是否允許整理后生成一個dataset對象。ValidResult參數(shù):指定有效的字段生成數(shù),如果小于1則不進(jìn)行判斷,否則如果 * 生成的最終列數(shù)與此值不符,則生成錯誤信息。StartCol參數(shù):指定額外的分隔列策略,大于0為不處理。小于1則表示以最大列加上此值為基準(zhǔn)行進(jìn)行倒序刪除, * 刪除位移為offerset參數(shù)指定的數(shù)值。ExtraSplit參數(shù):是否指定一系列列值進(jìn)行刪除,這些列可能是無規(guī)律的,如1、6、19列等。這些列的值將在Esplits參數(shù)數(shù)組中定義 * 注意Esplits數(shù)組的指定生效順序在StartCol參數(shù)之后,如果StartCol參數(shù)有效的話。obj_table參數(shù):是否有目標(biāo)參照表SQL語句返回的結(jié)果與文本列進(jìn)行對應(yīng) * XmlCfg 文件,如果您有XML配置文件,則可以忽略除openfile以外所有的參數(shù)傳遞,本函數(shù)將分析此配置文件的內(nèi)容,如果分析失敗則整個函數(shù)將失敗 *ref_maxcolid,由用戶指定在打開文本文件之后應(yīng)該生成的最大的列,一般這個參數(shù)用于最后一列都為空的情況,因為這樣EXCEL無法定位最后一個單元格,如果為0則跳過 */ public object[] OpenTextToExcelFile(string OpenFile, string SplitChar, string[,] ReplaceChars, int ValidResult, bool ExtraSplit, int[] Esplits, object[,] AddCols, int ref_maxcolid, int StartCol = 1, int offerset = 1) { object[] rv = new object[4]; rv[0] = ""; //存儲返回生成的EXCEL文件 rv[1] = ""; //返回錯誤信息或附加的信息 rv[2] = null; rv[3] = ""; try { //創(chuàng)建EXCEL應(yīng)用對象 ExcelApplication excel = new ExcelApplication(); Workbooks workbook = excel.Workbooks; object[,] dlist = new object[ref_maxcolid, 2]; for (int i = 0; i < ref_maxcolid; i++) { dlist[i, 0] = i + 1; dlist[i, 1] = Excel.XlColumnDataType.xlTextFormat; } workbook.OpenText(OpenFile, 20936, 1, Excel.XlTextParsingType.xlDelimited, Excel.XlTextQualifier.xlTextQualifierDoubleQuote, false, false, false, false, false, true, SplitChar, dlist, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); Excel.Range _range; int maxcolid = excel.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing).Column; if (ref_maxcolid > 0) { maxcolid = ref_maxcolid; } int maxrowid = excel.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing).Row; int _addcol = 0; if (AddCols != null) { _addcol = AddCols.GetLength(0); } int delcount = 0; if (StartCol <= 0) { for (int i = (maxcolid + StartCol); i >= 1; i -= offerset) { _range = excel.get_Range(excel.Cells[1, i], excel.Cells[65536, i]); _range.Select(); _range.Delete(Type.Missing); delcount++; } } if ((ExtraSplit) && (Esplits != null)) { for (int j = 0; j < Esplits.GetLength(0); j++) { int colid = Esplits[j]; _range = excel.get_Range(excel.Cells[1, colid], excel.Cells[65536, colid]); _range.Select(); _range.Delete(Type.Missing); delcount++; } } if ((ValidResult > 0) && ((maxcolid - delcount + _addcol) != ValidResult)) { rv[1] = "生成的最終數(shù)據(jù)結(jié)果與指定的列數(shù)目不符合。\r\n用戶指定的有效列為:" + ValidResult.ToString() + "\r\n系統(tǒng)生成的列:" + (maxcolid - delcount).ToString() + "附加的列:" + _addcol.ToString() + "\r\n系統(tǒng)檢測到的最大列:" + maxcolid.ToString(); //返回錯誤信息 return rv; } //創(chuàng)建模板的映像解析文件,最終以變量 desfilename 為輸出對象 FileEx commonApi = new FileEx(); string _file = "", _path = ""; _path = Path.GetDirectoryName(OpenFile); if (_path.Length > 3) { _path += "\\"; } _file = Path.GetFileNameWithoutExtension(OpenFile); string _validfilename = commonApi.GetValidFileName(_path, _file, ".xlsx"); string _lastfile = _path + _validfilename; rv[0] = _lastfile; if (File.Exists(_lastfile)) { File.Delete(_lastfile); } Worksheet worksheet = (Worksheet)excel.ActiveSheet; //解決替換字符的要求 if (ReplaceChars != null) { for (int i = 0; i < ReplaceChars.GetLength(0); i++) { string _find = ReplaceChars[i, 0], _rep = ReplaceChars[i, 1]; worksheet.Cells.Replace(_find, _rep, Excel.XlLookAt.xlPart, Excel.XlSearchOrder.xlByRows, false, false, false, false); } } _range = excel.get_Range(excel.Cells[1, 1], excel.Cells[1, 1]); _range.EntireRow.Insert(Type.Missing, Type.Missing); if (AddCols != null) { int ref_col = 0; string ref_fname = "", ref_fvalue = ""; Excel.Range _newrange; for (int ad = 0; ad < AddCols.GetLength(0); ad++) { ref_col = (int)AddCols[ad, 0]; ref_fname = AddCols[ad, 1].ToString(); ref_fvalue = AddCols[ad, 2].ToString(); _range = excel.get_Range(excel.Cells[1, ref_col], excel.Cells[1, ref_col]); _range.EntireColumn.Insert(Type.Missing, Type.Missing); // ref_col=_newrange.Column; excel.Cells[1, ref_col] = ref_fname; if (maxrowid > 0) { excel.Cells[2, ref_col] = ref_fvalue; _newrange = excel.get_Range(excel.Cells[2, ref_col], excel.Cells[2, ref_col]); _newrange.Copy(excel.get_Range(excel.Cells[2, ref_col], excel.Cells[maxrowid + 1, ref_col])); } } } worksheet.SaveAs(@_lastfile, Excel.XlFileFormat.xlAddIn, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value); excel.ActiveWorkbook.Close(false, Type.Missing, Type.Missing); excel.Quit(); rv[1] = "準(zhǔn)備數(shù)據(jù)成功,共有記錄" + maxrowid.ToString() + "行。字段" + (maxcolid - delcount + _addcol).ToString() + "列。"; } catch (Exception e) { rv[0] = ""; rv[1] = e.Message; } return rv; }
調(diào)用
調(diào)用示例代碼如下:
string splitchar = "#"; int validResult = 4; int origin = 65001; //utf-8 bool ConsecutiveDelimiter=true; //如果為 true,則將連續(xù)分隔符視為一個分隔符,如“##” 則視為“#” object[,] AddCols = new object[1, 3]; AddCols[0,0]=4; AddCols[0,1]="導(dǎo)入標(biāo)志"; AddCols[0,2] = "是"; object[] rv2 = OpenTextToExcelFile("d:\\std.txt", "d:\\std.xls", splitchar, null, validResult, false, null, AddCols, 0, 1, 1, origin, ConsecutiveDelimiter); Response.Write("result:"+rv2[0] + "<br>" + rv2[1]);
導(dǎo)入的文本文件示例(以兩個#號為分隔符)如下圖:
導(dǎo)入成功后如下圖所示:
小結(jié)
1、OpenTextToExcelFile方法是一種兼容舊 EXCEL 版本的寫法(如2003),我們可以根據(jù)實際需要進(jìn)行改造。
2、許多參數(shù)是根據(jù)我們在使用過程中的實際需要而設(shè)置,以滿足特殊需要,簡化后期處理。
3.原始文件的編碼請參照本文Excel 的文本文件導(dǎo)入功能部分的圖示所示,選擇框中就是對應(yīng)的編碼代碼,如65001表示UTF-8,這也是默認(rèn)值。20936 則表示簡體中文(GB2312-80)等等。
到此這篇關(guān)于C#實現(xiàn)格式化文本并導(dǎo)入到Excel的文章就介紹到這了,更多相關(guān)C#格式化文本內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#使用Jquery zTree實現(xiàn)樹狀結(jié)構(gòu)顯示 異步數(shù)據(jù)加載
這篇文章主要為大家詳細(xì)介紹了C#使用Jquery zTree實現(xiàn)樹狀結(jié)構(gòu)顯示和異步數(shù)據(jù)加載,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-12-12解決用Aspose.Words,在word文檔中創(chuàng)建表格的實現(xiàn)方法
本篇文章是對利用Aspose.Words,在word文檔中創(chuàng)建表格的實現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05在WCF數(shù)據(jù)訪問中使用緩存提高Winform字段中文顯示速度的方法
這篇文章主要介紹了在WCF數(shù)據(jù)訪問中使用緩存提高Winform字段中文顯示速度的方法,是非常實用的功能,需要的朋友可以參考下2014-09-09