C#實(shí)現(xiàn)格式化文本并導(dǎo)入到Excel
需求
在一些導(dǎo)入功能里,甲方經(jīng)常會(huì)給我們一些格式化的文本,類(lèi)似 CSV 那樣的純文本。比如有關(guān)質(zhì)量監(jiān)督的標(biāo)準(zhǔn)文件(如國(guó)家標(biāo)準(zhǔn)、地方標(biāo)準(zhǔn)、企業(yè)標(biāo)準(zhǔn)等),還有一此國(guó)際標(biāo)準(zhǔn)文件等等。提供給我們的這些文件是文件尺寸比較大的純文本文件,文件內(nèi)容是格式化的文本,具有規(guī)律的分隔字符。Excel 本身提供有導(dǎo)入文本文件的功能,但由于標(biāo)準(zhǔn)制定和發(fā)布是比較頻繁,每次的導(dǎo)入與整理還是比較耗時(shí)的,因些實(shí)現(xiàn)文本文件導(dǎo)入到 Excel 的功能可以更快速的解決重復(fù)勞動(dòng)和錯(cuò)誤,實(shí)現(xiàn)流程自動(dòng)化的一環(huán)。
Excel 的文本文件導(dǎo)入功能
我們運(yùn)行 Excel ,點(diǎn)擊選擇打開(kāi)文本文件時(shí),會(huì)彈出一個(gè)導(dǎo)入向?qū)?,如下圖:
如圖我們需要選擇合適的文本文件原始編碼,輸入分隔符,選擇其它的選項(xiàng),如連續(xù)的分隔符號(hào)視分單個(gè)處理等。下面我們將介紹如何利用 COM 來(lái)實(shí)現(xiàn)這一操作的自動(dòng)化處理。
范例運(yùn)行環(huán)境
操作系統(tǒng): Windows Server 2019 DataCenter
操作系統(tǒng)上安裝 Office Excel 2016
.net版本: .netFramework4.7.1 或以上
開(kāi)發(fā)工具:VS2019 C#
配置Office DCOM
配置方法可參照我的文章《C# 讀取Word表格到DataSet》進(jìn)行處理和配置。
實(shí)現(xiàn)
組件庫(kù)引入
OpenTextToExcelFile
OpenTextToExcelFile方法返回 object[] 類(lèi)型,object[0] 返回生成成功的 Excel 文件地址,object[1]返回錯(cuò)誤信息,其實(shí)體為 string 類(lèi)型。方法參數(shù)據(jù)說(shuō)明見(jiàn)下表:
序號(hào) | 參數(shù) | 類(lèi)型 | 說(shuō)明 |
---|---|---|---|
1 | OpenFile | string | 打開(kāi)的文本文件的絕對(duì)完整路徑及名稱(chēng)。 |
2 | ExcelFile | string | 要生成的Excel文件完整路徑地址。 |
3 | SplitChar | string | 分隔符 |
4 | ReplaceChars | string[,] | 這是一個(gè)導(dǎo)入后數(shù)據(jù)整理型參數(shù)。一個(gè)二維數(shù)組,用于導(dǎo)入后替換相關(guān)字符的數(shù)組,第一維為查找字符串 ,第二維為要替換的字符串。 |
5 | ValidResult | int | 這是一個(gè)檢驗(yàn)型參數(shù)。指定有效的字段生成數(shù),如果小于1則不進(jìn)行判斷,否則如果生成的最終列數(shù)與此值不符,則生成錯(cuò)誤信息以示警告。 |
6 | ExtraSplit | bool | 是否允許刪除指定的一系列列值。 |
7 | Esplits | int[] | 當(dāng)ExtraSplit為true時(shí),些數(shù)據(jù)生效,如定義1、6、19列等。這些列的值將在Esplits參數(shù)數(shù)組中定義。Esplits數(shù)組的指定生效順序在StartCol參數(shù)之后 |
8 | AddCols | object[,] | 這是一個(gè)整理型參數(shù)。表示要添加幾個(gè)固定列及固定值,維度包括3列,如object[0,0] 存儲(chǔ)要寫(xiě)入的列id,object[0,1] 存儲(chǔ)列id的標(biāo)題值,object[0,2] 存儲(chǔ)列id的值。示例如下: object[0,0]=10; object[0,1]="導(dǎo)入標(biāo)志"; object[0,2]="是"; |
9 | ref_maxcolid | int | 指定在打開(kāi)文本文件之后應(yīng)該生成的最大的列,一般這個(gè)參數(shù)用于最后一列都為空的情況,因?yàn)檫@樣EXCEL無(wú)法定位最后一個(gè)單元格,如果為0則忽略 |
10 | StartCol | int | 這是一個(gè)整理型參數(shù)。指定額外的刪除列策略,默認(rèn)值為1,表示不處理,<=0 則表示刪除前幾列。即 Math.Abs(StartCol) 個(gè),默認(rèn)步長(zhǎng)為 1。 |
11 | offerset | int | 與StartCol參數(shù)配合,默認(rèn)值為1,表示刪除步長(zhǎng)。注意:改變此值會(huì)影響刪除列的個(gè)數(shù)。 |
12 | origin | int | 文本文件的原始編碼,默認(rèn)為 65001,即UTF-8 |
13 | ConsecutiveDelimiter | bool | 如果為 true,則將連續(xù)分隔符視為一個(gè)分隔符,如“##” 則視為“#”。 默認(rèn)值為 false。 |
代碼
方法完整代碼如下:
/*本方法通過(guò)打開(kāi)一個(gè)具有一定分隔格式的文本到EXCEL中,并且由EXCEL進(jìn)行整理 * openfile參數(shù):打開(kāi)的文件絕對(duì)完整路徑及名稱(chēng)。splitchar參數(shù):分隔符。ReplaceChars參數(shù):一個(gè)二維數(shù)組,用于整理后替換相關(guān)字符的數(shù)組,第一維為查找字符串 * ,第二維為要替換的字符串。allowtodataset參數(shù):是否允許整理后生成一個(gè)dataset對(duì)象。ValidResult參數(shù):指定有效的字段生成數(shù),如果小于1則不進(jìn)行判斷,否則如果 * 生成的最終列數(shù)與此值不符,則生成錯(cuò)誤信息。StartCol參數(shù):指定額外的分隔列策略,大于0為不處理。小于1則表示以最大列加上此值為基準(zhǔn)行進(jìn)行倒序刪除, * 刪除位移為offerset參數(shù)指定的數(shù)值。ExtraSplit參數(shù):是否指定一系列列值進(jìn)行刪除,這些列可能是無(wú)規(guī)律的,如1、6、19列等。這些列的值將在Esplits參數(shù)數(shù)組中定義 * 注意Esplits數(shù)組的指定生效順序在StartCol參數(shù)之后,如果StartCol參數(shù)有效的話(huà)。obj_table參數(shù):是否有目標(biāo)參照表SQL語(yǔ)句返回的結(jié)果與文本列進(jìn)行對(duì)應(yīng) * XmlCfg 文件,如果您有XML配置文件,則可以忽略除openfile以外所有的參數(shù)傳遞,本函數(shù)將分析此配置文件的內(nèi)容,如果分析失敗則整個(gè)函數(shù)將失敗 *ref_maxcolid,由用戶(hù)指定在打開(kāi)文本文件之后應(yīng)該生成的最大的列,一般這個(gè)參數(shù)用于最后一列都為空的情況,因?yàn)檫@樣EXCEL無(wú)法定位最后一個(gè)單元格,如果為0則跳過(guò) */ 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] = ""; //存儲(chǔ)返回生成的EXCEL文件 rv[1] = ""; //返回錯(cuò)誤信息或附加的信息 rv[2] = null; rv[3] = ""; try { //創(chuàng)建EXCEL應(yīng)用對(duì)象 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用戶(hù)指定的有效列為:" + ValidResult.ToString() + "\r\n系統(tǒng)生成的列:" + (maxcolid - delcount).ToString() + "附加的列:" + _addcol.ToString() + "\r\n系統(tǒng)檢測(cè)到的最大列:" + maxcolid.ToString(); //返回錯(cuò)誤信息 return rv; } //創(chuàng)建模板的映像解析文件,最終以變量 desfilename 為輸出對(duì)象 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ù)分隔符視為一個(gè)分隔符,如“##” 則視為“#” 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)入的文本文件示例(以?xún)蓚€(gè)#號(hào)為分隔符)如下圖:
導(dǎo)入成功后如下圖所示:
小結(jié)
1、OpenTextToExcelFile方法是一種兼容舊 EXCEL 版本的寫(xiě)法(如2003),我們可以根據(jù)實(shí)際需要進(jìn)行改造。
2、許多參數(shù)是根據(jù)我們?cè)谑褂眠^(guò)程中的實(shí)際需要而設(shè)置,以滿(mǎn)足特殊需要,簡(jiǎn)化后期處理。
3.原始文件的編碼請(qǐng)參照本文Excel 的文本文件導(dǎo)入功能部分的圖示所示,選擇框中就是對(duì)應(yīng)的編碼代碼,如65001表示UTF-8,這也是默認(rèn)值。20936 則表示簡(jiǎn)體中文(GB2312-80)等等。
到此這篇關(guān)于C#實(shí)現(xiàn)格式化文本并導(dǎo)入到Excel的文章就介紹到這了,更多相關(guān)C#格式化文本內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#使用Jquery zTree實(shí)現(xiàn)樹(shù)狀結(jié)構(gòu)顯示 異步數(shù)據(jù)加載
這篇文章主要為大家詳細(xì)介紹了C#使用Jquery zTree實(shí)現(xiàn)樹(shù)狀結(jié)構(gòu)顯示和異步數(shù)據(jù)加載,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12解決用Aspose.Words,在word文檔中創(chuàng)建表格的實(shí)現(xiàn)方法
本篇文章是對(duì)利用Aspose.Words,在word文檔中創(chuàng)建表格的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05在WCF數(shù)據(jù)訪問(wèn)中使用緩存提高Winform字段中文顯示速度的方法
這篇文章主要介紹了在WCF數(shù)據(jù)訪問(wèn)中使用緩存提高Winform字段中文顯示速度的方法,是非常實(shí)用的功能,需要的朋友可以參考下2014-09-09WPF使用觸發(fā)器需要注意優(yōu)先級(jí)問(wèn)題解決
本文主要介紹了WPF使用觸發(fā)器需要注意優(yōu)先級(jí)問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01Unity Shader實(shí)現(xiàn)徑向模糊效果
這篇文章主要為大家詳細(xì)介紹了Unity Shader實(shí)現(xiàn)徑向模糊效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08