说明:
源码引用于:https://github.com/mrjono1/FastExcel
由于,源码不支持在excel中添加特殊符号,故做了改动。改动如下:
cell.cs文件的 internal StringBuilder ToXmlString(SharedStrings sharedStrings, int rowNumber)方法里添加了文本特殊符号的处理。
cell.cs文件修改后如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Xml.Linq; namespace FastExcel { /// <summary> /// Contains the actual value /// </summary> public class Cell { /// <summary> /// Column Numnber (Starts at 1) /// </summary> public int ColumnNumber { get; set; } /// <summary> /// The value that is stored /// </summary> public object Value { get; set; } /// <summary> /// Defined name or the column letter(s) for column this cell is in /// </summary> public string ColumnName { get; } /// <summary> /// Raw underlying XElement of cell /// </summary> public XElement XElement { get; } /// <summary> /// List of defined names assigned to this cell /// *Does not include names of ranges this cell is within* /// </summary> public IReadOnlyList<string> CellNames { get; } /// <summary> /// First defined name assigned to cell or cell Letter + row number if no named defined. /// </summary> public string CellName { get { if (CellNames.Any()) return CellNames.FirstOrDefault(); return ColumnName + RowNumber; } } /// <summary> /// Number of the row this cell is on /// </summary> public int RowNumber { get; } /// <summary> /// Create a new Cell /// </summary> /// <param name="columnNumber">Column number starting at 1</param> /// <param name="value">Cell Value</param> public Cell(int columnNumber, object value) { if (columnNumber <= 0) { throw new Exception("Column numbers starting at 1"); } ColumnNumber = columnNumber; ColumnName = GetExcelColumnName(columnNumber); RowNumber = 0; Value = value; } /// <summary> /// Create a new Cell /// </summary> /// <param name="cellElement">Cell</param> /// <param name="worksheet">The worksheet that this cell is on</param> public Cell(XElement cellElement, Worksheet worksheet) { bool isTextRow = (from a in cellElement.Attributes("t") where a.Value == "s" select a).Any(); string columnName = (from a in cellElement.Attributes("r") select a.Value).FirstOrDefault(); string columnLetter = Regex.Replace(columnName, @"d", ""); RowNumber = Convert.ToInt32(Regex.Replace(columnName, @"[^d]", "")); ColumnName = worksheet.FastExcel.DefinedNames.FindColumnName(worksheet.Name, columnLetter) ?? columnLetter; CellNames = worksheet.FastExcel.DefinedNames.FindCellNames(worksheet.Name, columnLetter, RowNumber); ColumnNumber = GetExcelColumnNumber(columnName); XElement = cellElement; if (isTextRow) { Value = worksheet.FastExcel.SharedStrings.GetString(cellElement.Value); } else { // cellElement.Value will give a concatenated Value + reference/calculation var node = cellElement.Elements().Where(x => x.Name.LocalName == "v").SingleOrDefault(); if (node != null) { Value = node.Value; } else { Value = cellElement.Value; } } } internal StringBuilder ToXmlString(SharedStrings sharedStrings, int rowNumber) { StringBuilder cell = new StringBuilder(); if (Value != null) { bool isString = false; object value = Value; if (Value is int) { isString = false; } else if (Value is double) { isString = false; } else if (Value is string) { isString = true; } if (isString) { var strValue = value.ToString(); //执行特殊符号检查 //由于xml存字符的时候,一些特殊字符会造成错误,因此,需要将特殊字符替代成xml识别的字符 // " to " // ' to ' // < to < // > to > // & to & if (!string.IsNullOrEmpty(strValue)) { strValue = strValue.Replace("&", "&"); strValue = strValue.Replace("<", "<"); strValue = strValue.Replace(">", ">"); strValue = strValue.Replace(""", """); strValue = strValue.Replace("'", "'"); } value = sharedStrings.AddString(strValue); } cell.AppendFormat("<c r="{0}{1}"{2}>", GetExcelColumnName(ColumnNumber), rowNumber, (isString ? " t="s"" : string.Empty)); cell.AppendFormat("<v>{0}</v>", value); cell.Append("</c>"); } return cell; } //http://stackoverflow.com/questions/181596/how-to-convert-a-column-number-eg-127-into-an-excel-column-eg-aa /// <summary> /// Convert Column Number into Column Name - Character(s) eg 1-A, 2-B /// </summary> /// <param name="columnNumber">Column Number</param> /// <returns>Column Name - Character(s)</returns> public static string GetExcelColumnName(int columnNumber) { int dividend = columnNumber; string columnName = String.Empty; int modulo; while (dividend > 0) { modulo = (dividend - 1) % 26; columnName = string.Concat(Convert.ToChar(65 + modulo), columnName); dividend = (int)((dividend - modulo) / 26); } return columnName; } //http://stackoverflow.com/questions/181596/how-to-convert-a-column-number-eg-127-into-an-excel-column-eg-aa /// <summary> /// Covert Column Name - Character(s) into a Column Number eg A-1, B-2, A1 - 1, B9 - 2 /// </summary> /// <param name="columnName">Column Name - Character(s) optinally with the Row Number</param> /// <param name="includesRowNumber">Specify if the row number is included</param> /// <returns>Column Number</returns> public static int GetExcelColumnNumber(string columnName, bool includesRowNumber = true) { if (includesRowNumber) { columnName = Regex.Replace(columnName, @"d", ""); } int[] digits = new int[columnName.Length]; for (int i = 0; i < columnName.Length; ++i) { digits[i] = Convert.ToInt32(columnName[i]) - 64; } int mul = 1; int res = 0; for (int pos = digits.Length - 1; pos >= 0; --pos) { res += digits[pos] * mul; mul *= 26; } return res; } /// <summary> /// Merge the parameter cell into this cell /// </summary> /// <param name="cell">Cell to merge</param> public void Merge(Cell cell) { Value = cell.Value; } } }
测试代码:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using FastExcel; namespace FastExcelTest { class Program { static void Main(string[] args) { SaveExcel(); Console.WriteLine("ok"); Console.Read(); } private static void SaveExcel(string saveFileName = "testSave.xlsx") { FileInfo outputFile = new FileInfo(saveFileName); FileInfo epplusOutputFile = null; FileInfo templateFile = new FileInfo("Template.xlsx"); if (outputFile.Exists) { outputFile.Delete(); outputFile = new FileInfo(saveFileName); } using (FastExcel.FastExcel fastExcel = new FastExcel.FastExcel(templateFile, outputFile)) { //写入标题 Worksheet worksheet = new Worksheet(); worksheet.AddRow(new object[] { "标题1", "标题2", "属性1", "属性1" }); worksheet.AddRow(new object[] { "ssslkjl", "lkllkjffjfj", "在这里看节省了空间~!@#$%^&&*()_+{}|[]\、\;;',./<>?", "在这里看节省了空间~!@#$%^&&*()_+{}|[]\、\;;',./<>?" }); fastExcel.Write(worksheet, "sheet1"); } } } }