当前位置: 首页 > 工具软件 > Toxy > 使用案例 >

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

许博易
2023-12-01


我现在在一家大型制造业公司从事生产管理相关工作,管理离不开计划,计划离不开数据,数据离不开统计分析处理。产品的工序多,涉及到的人员、场地、设备、图纸、天气、潮水、原材料等等,关系复杂,不作讨论。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


 类似资料: