Ole Db ,NPOI/TOXY, VSTO混合编程

来源:互联网 发布:淘宝卖人参 编辑:程序博客网 时间:2024/05/22 06:10

我现在在一家大型制造业公司从事生产管理相关工作,管理离不开计划,计划离不开数据,数据离不开统计分析处理。产品的工序多,涉及到的人员、场地、设备、图纸、天气、潮水、原材料等等,关系复杂,不作讨论。45个项目,分为45个Excel表中,大约数据为1M个单元格。

这个软件的功能主要实现了ERP或者叫CIMS中计划管理的核心功能,此类ERP基本就是按企业管理定制,很难有软件能适用所有企业,每个企业管理水平,资源配置,人员素质等等都 不一样,

原本想采用BS结构做一个数据库程序,但是需求是不断改变的,而且任务非常急。采用EXCEL做平台可以省去做界面的时间,也可以省去做数据库的时间,同时还省去了培训的时间。软件是随时管理需求在不断变化。Excel在不需要安装特别的客户端,有很多现成的图表可以使用。现在的代码量大约是10K行,当然也有许多垃圾在里面,

不吹牛了,两年前采用C++的一个类写了一个仪器的上位机程序,最后数据存到EXCEL,是通过COM来操作的,但C++在处理这些不确定类型的时候感觉比较麻烦(也许是自己水平不够),类型转换到现在都还是晕的,, 要用的时候只能去查了。虽然 我一直希望把C++坚持下去,但C++做这些的高层应用,是太麻烦了。

C#之前开发过一个AUTOCAD的插件,虽然最后做了大半中止了,但核心功能都实现了。

采用VSTO也是看了微软的说明 ,推荐使用.net,正好自己也用过C#,感觉效率比C++要高,

核心代码主要经过了几次大修改。

第1版主要是采用全部采用COM来读写cell数据。

第2版采用OLE DB来读数据,写采用COM。

第3版采用OLE DB读  ,,写是通过WIN剪切板。

第4版采用OLE DB读,写是通过TOXY/NPOI

每次的修改都是为了读写性能的提升,程序运行在至强CPU上面,第4版之前,统计全部数据最长时间需要4小时。第4版统计现在最多2分钟。

本想第4版把读取也改为toxy/NPOI,最近太忙也没时间,性能已完全满足需求了,所以也不花时间在上面了。


以下函数是初始化EXCEL模板的,有个问题要注意就是EXCEL的XML文件中,所有的样式都是引用的样式的ID,而不是引用样式本身,如果有5种样式就要创建5个

workbook.CreateCellStyle(),分别赋予,,而不能只能创建一个。

      void init_npoi_workbook()        {            workbook = new XSSFWorkbook();            titlecellstyle = workbook.CreateCellStyle();            titlecellstyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;            titlecellstyle.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center;            titlecellstyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;            titlecellstyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;            titlecellstyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;            titlecellstyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;            titlecellstyle.WrapText = true;            for (int j = 0; j < block_count_weight_array.GetLength(1); j++)            {            cellstyle_array[j] = workbook.CreateCellStyle();            cellstyle_array[j].Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;            cellstyle_array[j].VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center;            cellstyle_array[j].BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;            cellstyle_array[j].BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;            cellstyle_array[j].BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;            cellstyle_array[j].BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;            cellstyle_array[j].WrapText = true;            cellstyle_array[j].BottomBorderColor = rowcolor[j];            cellstyle_array[j].TopBorderColor = rowcolor[j];            cellstyle_array[j].LeftBorderColor = rowcolor[j];            cellstyle_array[j].RightBorderColor = rowcolor[j];                        cfont1[j] = workbook.CreateFont();            cfont1[j].Color = rowcolor[j];            cellstyle_array[j].SetFont(cfont1[j]);            }            foreach (int column in count_columns)            {                //按周、月统计周期0为周,1为月                int cols_4_count = 0;                //if (0 == count_type)                //{                cols_4_count = count_countperoids;                ISheet sht = workbook.CreateSheet(column.ToString());                for (int j = 0; j < wlcountline_start; j++)                {                    for (int i = 0; i < count_countperoids + 2; i++)                    {                        sht.CreateRow(j).CreateCell(i);                    }                }                //用来滚动周次日期                DateTime date_roll = new DateTime();                DateTime date_current_start = cal_week_year_start(count_startdate);                //表头周历的第一周的第一天,循环过程中累加日期                date_roll = date_current_start.AddDays((cal_date_Year_week(count_startdate) - 1) * 7);                //周历第一天,计算起点                if (1 == count_type)                {                    d_year_start = date_roll;                }                IRow row = sht.CreateRow(4 - 1);                for (int m = 0; m < cols_4_count; m++)                {                    //填写表头上统计周期                    sht.GetRow(4 - 1).CreateCell(wlcountline_column_start + m * wlcountline_column_per_month);                    //sht.CreateRow(4 - 1).CreateCell(wlcountline_column_start + m * wlcountline_column_per_month - 1);                    //sht.CreateRow(4 - 1).CreateCell(wlcountline_column_start + m * wlcountline_column_per_month );                    //      regon = new CellRangeAddress(4 - 1, 4 - 1, wlcountline_column_start + m * wlcountline_column_per_month - 1, wlcountline_column_start + m * wlcountline_column_per_month);                    //   sht.AddMergedRegion(regon);                    //日                    if (0 == count_type)                    {                        sht.GetRow(4 - 1).CreateCell(wlcountline_column_start + m * wlcountline_column_per_month - 1).SetCellValue(d_year_start.AddDays(m).ToShortDateString());                        //   sht.GetRow(4 - 1).GetCell( wlcountline_column_start + m * wlcountline_column_per_month - 1).SetCellValue() = "yyyy-m-d";                    }                    //周                    else if (1 == count_type)                    {                        string st1 = "";                        st1 = cal_date_year(date_roll).ToString() + "-W" + cal_date_Year_week(date_roll).ToString() + "\n(" + date_roll.ToShortDateString() + ")";                        row.CreateCell(wlcountline_column_start + m * wlcountline_column_per_month - 1).SetCellValue(st1);                        date_roll = date_roll.AddDays(7);                    }                    //月                    else if (2 == count_type)                    {                        DateTime d_start;                        if (count_startdate.Day >= count_month_start)                        {                            //下月起始时间                            d_start = new DateTime(count_startdate.AddMonths(m + 1).Year, count_startdate.AddMonths(m + 1).Month, count_month_start);                        }                        else                        {                            //本月的起始时间                            d_start = new DateTime(count_startdate.AddMonths(m).Year, count_startdate.AddMonths(m).Month, count_month_start);                        }                        sht.GetRow(4 - 1).CreateCell(wlcountline_column_start + m * wlcountline_column_per_month - 1).SetCellValue(d_start.Year.ToString() + "-M" + d_start.Month.ToString());                    }                    regon = new CellRangeAddress(4 - 1, 4 - 1, wlcountline_column_start + m * wlcountline_column_per_month - 1, wlcountline_column_start + m * wlcountline_column_per_month );                    sht.AddMergedRegion(regon);                }            }        }




以下是将统计结果从内存数组写到文件中,

       public void toxy_writecache()        {            Excel.Application app = App;            // app.ScreenUpdating = false;            //try            //{            //    workbook = new XSSFWorkbook();            //}            //catch (Exception ex)            //{            //    MessageBox.Show(ex.Message + ex.StackTrace);            //}            ICell cell, cell2;            foreach (int column in count_columns)            {                ISheet sheet = workbook.GetSheet(column.ToString());                IRow row;                for (int j = 0; j < block_count_weight_array.GetLength(1); j++)                {                    row = sheet.CreateRow(wlcountline_start + shipindex * temp_rows_4_ship + 3 * j - 1);                    //边框颜色                      //cellstyle.BottomBorderColor = rowcolor[j];                    //cellstyle.TopBorderColor = rowcolor[j];                    //cellstyle.LeftBorderColor = rowcolor[j];                    //cellstyle.RightBorderColor = rowcolor[j];                    cellstyle = cellstyle_array[j];                    for (int m = 0; m < 2; m++)                    {                        cell = row.CreateCell(m);                        cell.CellStyle = cellstyle;                    }                    int length = 0;                    //   row = sheet.CreateRow(  j);                    //分段清单明细,每2列填1列,                    for (int k = 0; k < block_count_weight_array.GetLength(2); k += 2)                    {                        cell = row.CreateCell(k + 2);                        cell2 = row.CreateCell(k + 1 + 2);                        regon = new CellRangeAddress(cell.RowIndex, cell.RowIndex, cell.ColumnIndex, cell.ColumnIndex + 1);                        cell.CellStyle = cellstyle;                        cell2.CellStyle = cellstyle;                        sheet.AddMergedRegion(regon);                        cell.SetCellValue(block_array[column, j, k]);                        if (length < block_array[column, j, k].Length)                        {                            length = block_array[column, j, k].Length;                        }                    }                    Int16 height = Convert.ToInt16(length / 17 * 15 * 8);                    if (height < 15)                    {                        height = 15;                    }                    // row.Height = 80;                    row = sheet.CreateRow(wlcountline_start + shipindex * temp_rows_4_ship + 3 * j);                    for (int m = 0; m < 2; m++)                    {                        cell = row.CreateCell(m);                        cell.CellStyle = cellstyle;                    }                    for (int k = 0; k < block_count_weight_array.GetLength(2); k++)                    {                        if (k % 2 == 1)                        {                            cell = row.CreateCell(k + 2);                            cell.CellStyle = cellstyle;                            cell.SetCellValue("数量");                        }                        else                        {                            cell = row.CreateCell(k + 2);                            cell.CellStyle = cellstyle;                            cell.SetCellValue("重量");                        }                    }                    row = sheet.CreateRow(wlcountline_start + shipindex * temp_rows_4_ship + 3 * j + 1);                    for (int m = 0; m < 2; m++)                    {                        cell = row.CreateCell(m);                        cell.CellStyle = cellstyle;                    }                    for (int k = 0; k < block_count_weight_array.GetLength(2); k++)                    {                        cell = row.CreateCell(k + 2);                        cell.CellStyle = cellstyle;                        cell.SetCellValue(block_count_weight_array[column, j, k]);                    }                    regon = new CellRangeAddress(wlcountline_start + shipindex * temp_rows_4_ship + 3 * j, wlcountline_start + shipindex * temp_rows_4_ship + 3 * j + 1, 1, 1);                    sheet.AddMergedRegion(regon);                    sheet.GetRow(wlcountline_start + shipindex * temp_rows_4_ship + 3 * j - 1).GetCell(1).SetCellValue(shipprojectname);                    sheet.GetRow(wlcountline_start + shipindex * temp_rows_4_ship + 3 * j).GetCell(1).SetCellValue(rowname[j]);                    if (j == block_count_weight_array.GetLength(1) - 1)                    {                        regon = new CellRangeAddress(wlcountline_start + shipindex * temp_rows_4_ship - 1, wlcountline_start + shipindex * temp_rows_4_ship + 3 * j + 1, 0, 0);                        sheet.AddMergedRegion(regon);                        sheet.GetRow(wlcountline_start + shipindex * temp_rows_4_ship - 1).GetCell(0).SetCellValue(shipindex + 1);                    }                }            }        }



附上剪切板写入EXCEL的函数

        public void Write_cache()        {            Excel.Application app = App;            // app.ScreenUpdating = false;            Excel.Worksheet count_start_sheet = null;            object m_objOpt = System.Reflection.Missing.Value;            foreach (int column in count_columns)            {                //先按列名与统计表的表名比较得到表对象                for (int i = 0; i < wlbookcount.Worksheets.Count; i++)                {                    if (wlbookcount.Worksheets.get_Item(i + 1).Name == column.ToString())                    {                        count_start_sheet = wlbookcount.Worksheets.get_Item(i + 1);                    }                }                //输出至剪切板,再粘贴                int col_total = 0;                if (count_type == 0)                {                    col_total = 54;                }                else                {                    col_total = 12;                }                for (int j = 0; j < block_count_weight_array.GetLength(1); j++)                {                    string sData = "";                    bool data_ed = false;                    for (int k = 0; k < block_count_weight_array.GetLength(2); k += 2)                    {                        if (k < block_count_weight_array.GetLength(2) - 2)                        //if (block_array[column, j, k] == "")                        //    sData += "\t\t";                        //else                        {                            sData += block_array[column, j, k] + "\t\t";                            data_ed = true;                        }                        else                        //if (block_array[column, j, k] == "")                        //    sData += "\t\r\n";                        //else                        {                            sData += block_array[column, j, k] + "\t\r\n";                            data_ed = true;                        }                        //if (k >= col_total)                        //{                        //    break;                        //}                    }                    if (data_ed)                    {                        System.Windows.Forms.Clipboard.SetDataObject(sData);                        Excel.Range rg = count_start_sheet.Cells.get_Item(wlcountline_start + shipindex * temp_rows_4_ship + 3 * j, 3);                        count_start_sheet.Activate();                        count_start_sheet.Paste(rg, false);                    }                }                for (int j = 0; j < block_count_weight_array.GetLength(1); j++)                {                    string sData = "";                    bool data_ed = false;                    for (int k = 0; k < block_count_weight_array.GetLength(2); k++)                    {                        if (k < block_count_weight_array.GetLength(2) - 1)                        //if (block_count_weight_array[column, j, k] > 0.1f)                        {                            sData += block_count_weight_array[column, j, k].ToString() + "\t";                            data_ed = true;                        }                        //else                        //    sData += "0\t";                        else                        //if (block_count_weight_array[column, j, k] > 0.1f)                        {                            sData += block_count_weight_array[column, j, k].ToString() + "\r\n";                            data_ed = true;                        }                        //else                        //    sData += "0\r\n";                    }                    if (data_ed)                    {                        System.Windows.Forms.Clipboard.SetDataObject(sData);                        Excel.Range rg = count_start_sheet.Cells.get_Item(wlcountline_start + shipindex * temp_rows_4_ship + 2 + 3 * j, 3);                        count_start_sheet.Activate();                        count_start_sheet.Paste(rg, false);                    }                }                /*                for (int j = 0; j < block_array.GetLength(1); j++)                {                    for (int k = 0; k < block_array.GetLength(2); k += 2)                    {                        if (block_array[column, j, k] != "")                        count_start_sheet.Cells.get_Item(wlcountline_start + shipindex * temp_rows_4_ship + 3 * j, wlcountline_column_start + k).Value = block_array[column, j, k];                    }                }                for (int j = 0; j < block_count_weight_array.GetLength(1); j++)                {                    for (int k = 0; k < block_count_weight_array.GetLength(2); k++)                    {                       if (block_count_weight_array[column, j, k] > 0.1)                           count_start_sheet.Cells.get_Item(wlcountline_start + shipindex * temp_rows_4_ship + 2 + 3 * j, wlcountline_column_start + k).Value = block_count_weight_array[column, j, k];                    }                }                 */                //    app.ScreenUpdating = false;            }        }




另,引这个库的时候报了一个异常,在NPOI的群中询问也没得到结果,最后是直接在VS的异常监控中把这个项去掉就行了,程序工作正常。

TOXY、NPOI的功能远不止读写EXCEL文件,其他 的功能没有用过,就不作讨论了。


水平有限,如有错误 ,敬请指出。



在此要感谢TONY Qu,他是toxy /NPOI的作者,

npoi.codeplex.com
toxy.codeplex.com


0 0