C#批量转CSV到Excel

版权声明:转载需注明本博客的链接 https://blog.csdn.net/someboy53/article/details/82120199

今天在给另一个系统准备数据时,需要将很多个CSV文件转换成Excel文件。本来说这么简单一个事情,网上应该有现成的解决方案或者程序来处理,结果找了一下午,发现不是这儿有问题,就是那儿有问题,最大的问题就是转移后的Excel的长数字存在丢失精度的现象。

当然丢失精度的问题,可以通过对CSV文件进行处理解决,有以下几种办法:

  1. 在长数字字符串之前增加单引号,但是如果有一列长数字是空时,这个单引号就会显示出来
  2. 用双引号将长数字字符串包住,再加前面加上=号,以给Excel说明这个字段是一个字符串公式,但是和上面有同样的问题

最后只能自己编程解决,引用Aspose.Cells的早期版本,因为新版要给钱。(当然也可以使用Microsoft.Office.Excel类,稍微要麻烦一点),思路为:

  1. 读取CSV所在目录中所有CSV文件
  2. 对文件进行循环处理
  3. 每次读入1024个字节,并判断是否为另一行(0x2a && 引号成对)
  4. 如果一行完结,则将之前的这一行的数据写入Excel的行中
  5. 如果未完结,则继续读取
  6. 文件读完,设置之前所有单元格为文本格式,并写Excel文件,并开始下一文件。

核心代码如下:

    class AsposeExcel
    {
        private string outFileName = "";
        private Workbook book = null;
        private Worksheet sheet = null;
        private int startRow = 0;

        public AsposeExcel()
        {
        }

        public AsposeExcel(string outfilename)
        {
            outFileName = outfilename;
        }

        private void NewBook()
        {
            book = new Workbook();
            sheet = book.Worksheets[0];
            qLevel = 0;
            sb = new StringBuilder();
            lineEnd = false;
            cells = new List<string>();
            startRow = 0;
            maxColumns = 0;
        }

        //引号层级

        private int qLevel = 0;
        private System.Text.StringBuilder sb = new StringBuilder();
        private bool lineEnd = false;
        private int maxColumns = 0;
        //private char[] lastChars;
        private List<string> cells = new List<string>();

        private void AddBody(char[] chars, int len)
        {
            int i;
            for (i = 0; i < len; i++)
            {
                if (chars[i] == ',' && qLevel == 0)
                {
                    //一段结束,开始下一段
                    cells.Add(sb.ToString());
                    sb.Clear();
                    continue;
                }
                if (chars[i] == '"' && qLevel == 0)
                {
                    qLevel = 1;
                    continue;
                }
                if (chars[i] == '"' && qLevel == 1)
                {
                    qLevel = 0;
                    continue;
                }
                if (chars[i] == 0x0a && qLevel == 0)
                {
                    lineEnd = true;
                    //break;
                }
                sb.Append(chars[i]);
                if (lineEnd)
                {
                    cells.Add(sb.ToString());
                    sb.Clear();
                    for (int col = 0; col < cells.Count; col++)
                    {
                        Cell cell = null;
                        cell = sheet.Cells[startRow, col];
                        cell.PutValue(cells[col]);
                    }
                    maxColumns = maxColumns > cells.Count ? maxColumns : cells.Count;
                    startRow += 1;
                    lineEnd = false;
                    cells.Clear();
                }
            }
        }

        private void Save()
        {
            try
            {
                Aspose.Cells.Range r = sheet.Cells.CreateRange(0, 0, startRow, maxColumns);
                Aspose.Cells.Style s = book.Styles[book.Styles.Add()];
                s.Custom = "@";
                StyleFlag sf = new StyleFlag();
                sf.NumberFormat = true;
                r.ApplyStyle(s, sf);

                sheet.AutoFitColumns();

                book.Save(outFileName);

            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public void convert(FileInfo fi, string outputPath)
        {
            this.NewBook();
            FileStream fs = fi.OpenRead();
            TextReader tr = new StreamReader(fs, Encoding.GetEncoding("gb2312"), true);
            this.outFileName = Path.Combine(outputPath, Path.GetFileNameWithoutExtension(fi.Name) + ".xlsx");
            //ae.AddHeader(tr.ReadLine());
            char[] buf = new char[1024];
            int len = tr.Read(buf, 0, 1024);
            while (len > 0)
            {
                AddBody(buf, len);
                len = tr.Read(buf, 0, 1024);
            }
            Save();
        }
    }
最后附上编译好的文件,需要.net 4.0 Framework

    下载

猜你喜欢

转载自blog.csdn.net/someboy53/article/details/82120199
今日推荐