慶軍之導出excel 利用npoi基於模板導出excel

不想廢話。本來想用反射,試了一把。寫的讓我崩潰。最後小僧啓發了我,我改用JObject來處理綁定的問題。源代碼如下。垃圾代碼,自己記錄下。

public class WriteExcelDataDefine
        {
            public int RowIndex { get; set; }
            public int CellIndex { get; set; }

            /// <summary>
            /// 0空格不管
            /// 3子對象
            /// 4綁定對象
            /// 5常量
            /// </summary>
            public byte WriteType { get; set; }

            /// <summary>
            /// 0 單行
            /// 1 綁定多行
            /// </summary>
            public byte WriteMode { get; set; }
            public string DataType { get; set; }//data.fuck data 如果是固定字符 不填
            public string DataContent { get; set; }//data.fuck fuck 如果是固定字符 sss sss

            /// <summary>
            /// 佔用行數
            /// </summary>
            public int MaxWriteRowCount { get; set; } = -1;

            /// <summary>
            /// 數據源行
            /// </summary>
            public int SourceCount { get; set; } = 1;
        }

        /// <summary>
        /// 解析Excel到數據綁定1
        /// </summary>
        /// <param name="filepath"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public List<WriteExcelDataDefine> TemplatePareExcelDefineSetup1(string filepath)
        {
            if (!File.Exists(filepath))
            {
                throw new Exception("模板不存在");
            }

            IWorkbook workbook = null;
            //string extension = Path.GetExtension(url);
            using (FileStream fs = System.IO.File.OpenRead(filepath))
            {
                //把xlsx文件中的數據寫入workbook中
                workbook = new XSSFWorkbook(fs);
            }

            ISheet sheet = workbook.GetSheetAt(0);//目前只支持一個sheet,並且在第一個

            List<WriteExcelDataDefine> writeExcelDatas = new List<WriteExcelDataDefine>(100);

            //Dictionary<Point, string> excelBind = new Dictionary<Point, string>(100);
            for (int rowindex = 0; rowindex <= sheet.LastRowNum; rowindex++)
            {
                IRow onerow = sheet.GetRow(rowindex);
                if (onerow == null)
                {
                    continue;
                }

                for (int colindex = 0; colindex < onerow.LastCellNum; colindex++)
                {
                    var onecellvalue = onerow.GetCell(colindex)?.ToString();
                    if (string.IsNullOrWhiteSpace(onecellvalue))
                    {
                        continue;
                    }

                    if (onecellvalue.StartsWith("#[")
                        && onecellvalue.EndsWith("]"
                        ))
                    {
                        if (onecellvalue.IndexOf(".") > 0)//可能是子對象
                        {
                            var datatypedefines = onecellvalue.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
                            if (datatypedefines.Length != 2)//不支持多層路徑暫時或者寫錯了
                            {
                                writeExcelDatas.Add(new WriteExcelDataDefine()
                                {
                                    RowIndex = rowindex,
                                    CellIndex = colindex,
                                    DataContent = onecellvalue,
                                    DataType = "",
                                    MaxWriteRowCount = 1,
                                    WriteType = 5
                                });
                            }
                            else//
                            {
                                writeExcelDatas.Add(new WriteExcelDataDefine()
                                {
                                    RowIndex = rowindex,
                                    CellIndex = colindex,
                                    DataContent = datatypedefines[1].Replace("]", ""),
                                    DataType = datatypedefines[0].Replace("#[", ""),
                                    MaxWriteRowCount = -1,
                                    WriteType = 3
                                });
                            }
                        }
                        else
                        {
                            writeExcelDatas.Add(new WriteExcelDataDefine()
                            {
                                RowIndex = rowindex,
                                CellIndex = colindex,
                                DataContent = onecellvalue.Replace("#[", "").Replace("]", ""),
                                DataType = "",
                                MaxWriteRowCount = -1,
                                WriteType = 4
                            });
                        }
                    }
                    else//常量只能爲一行 應該是非綁定值
                    {
                        writeExcelDatas.Add(new WriteExcelDataDefine()
                        {
                            RowIndex = rowindex,
                            CellIndex = colindex,
                            DataContent = onecellvalue,
                            DataType = "",
                            MaxWriteRowCount = 1,
                            WriteType = 5
                        });
                    }
                }
            }

            //刪掉沒有必要轉換的常量行
            var orderbyRows = writeExcelDatas.GroupBy(q => q.RowIndex).OrderBy(q => q.Key);
            List<int> removeRowIndex = new List<int>(orderbyRows.Count());
            foreach (var item in orderbyRows)//按行來分析
            {
                if (item.All(q => q.WriteType == 5))
                {
                    removeRowIndex.Add(item.First().RowIndex);
                }
            }

            if (removeRowIndex.Count > 0)
            {
                foreach (var item in removeRowIndex)
                {
                    writeExcelDatas.RemoveAll(q => q.RowIndex == item);
                }
            }

            return writeExcelDatas;
        }

        public void DataBindPareExcelDefineSetup2(string filepath,
            List<WriteExcelDataDefine> excelDataDefines, object datas)
        {
            

            JToken data = JToken.FromObject(datas);
            //dynamic New = JObject.FromObject(data);

            //DataTable   dt = new DataTable();
            //Dictionary<string,string>
            //var t = typeof(T);
            Dictionary<string, int> mTableDefines = new Dictionary<string, int>(excelDataDefines.Count);
            var orderbyRows = excelDataDefines.GroupBy(q => q.RowIndex).OrderBy(q => q.Key);

            foreach (var item in orderbyRows)//按行來分析
            {

                var orderbyCells = item.OrderBy(q => q.CellIndex);//按列排序
                //找到所有的數據綁定
                //var alldatabindCells = orderbyCells.Where(q=>q.WriteType == 3 && q.WriteType == 4).Distinct().ToList();
                //var alltps = t.GetProperties();
                //var tName = t.GetName();

                //判斷綁定對象的類型
                //if (TestIEnumerable(t))//需要循環
                //{
                setbindPObjects(data,
                    mTableDefines, orderbyCells);

                var maxrowCount = item.Max(q => q.MaxWriteRowCount);
                foreach (var cellname in item)
                {
                    cellname.MaxWriteRowCount = maxrowCount;
                }

            }//重新設置行

            IWorkbook workbook = null;
            //string extension = Path.GetExtension(url);
            using (FileStream fs = System.IO.File.OpenRead(filepath))
            {
                //把xlsx文件中的數據寫入workbook中
                workbook = new XSSFWorkbook(fs);
            }

            ISheet sheet = workbook.GetSheetAt(0);//目前只支持一個sheet,並且在第一個

            int currentrowIndex = 0;//模板行所在的位置
            int addrowCount = 0;


            //開始渲染
            foreach (var item in orderbyRows)//按行來分析
            {
                //addrowCount += 1;
                var onerowitem = item.First();


                
                for (int datarowindex = 0; datarowindex < onerowitem.MaxWriteRowCount; datarowindex++)
                {


                    currentrowIndex = addrowCount + onerowitem.RowIndex;
                    //重新計算了模板行的位置

                    IRow writeRow = null;
                    if (datarowindex == 0)//模板行所在,直接用
                    {
                        writeRow = sheet.GetRow(currentrowIndex);
                    }
                    else
                    {
                        sheet.CreateRow(currentrowIndex + 1);//新行
                        writeRow = sheet.CopyRow(currentrowIndex, currentrowIndex+1);//複製上一行到新行
                    }


                    //按列排序 寫列的數據
                    foreach (var cellitem in item.OrderBy(q => q.CellIndex))
                    {
                        //寫數據
                        if (cellitem.WriteType == 0) continue;

                        var writeCell = writeRow.GetCell(cellitem.CellIndex);

                        if (cellitem.WriteType == 5)//常量
                        {
                            writeCell.SetCellValue(cellitem.DataContent ?? "");
                            continue;
                        }//寫入常量

                        if (cellitem.WriteType == 4)//綁定對象
                        {
                            if (cellitem.WriteMode == 0)//對象不是數組
                            {
                                if (data.Type == JTokenType.Array)
                                {
                                    writeCell.SetCellValue(((JArray)data)[0][cellitem.DataContent]?.ToString());
                                }
                                else
                                {
                                    writeCell.SetCellValue(((JObject)data)[cellitem.DataContent]?.ToString());
                                }
                            }
                            else//多行
                            {
                                if (data.Type == JTokenType.Array)
                                {
                                    //獲取當前行
                                    //var currentjrow = 1;
                                    if (cellitem.SourceCount < datarowindex)
                                    {
                                        writeCell.SetCellValue(((JArray)data)[0][cellitem.DataContent]?.ToString());
                                    }
                                    else
                                    {
                                        writeCell.SetCellValue(((JArray)data)[datarowindex][cellitem.DataContent]?.ToString());

                                    }
                                }
                                else
                                {
                                    writeCell.SetCellValue(((JObject)data)[cellitem.DataContent]?.ToString());
                                }
                            }
                        }

                        if (cellitem.WriteType == 3)//子對象
                        {
                            if (cellitem.WriteMode == 0)//單行
                            {
                                if (data.Type == JTokenType.Array)
                                {
                                    var bindsonObj = ((JArray)data)[0][cellitem.DataType];
                                    if (bindsonObj.Type == JTokenType.Array)
                                    {
                                        //獲取當前行
                                        writeCell.SetCellValue(((JArray)bindsonObj)[0][cellitem.DataContent]?.ToString());
                                    }
                                    else
                                    {
                                        writeCell.SetCellValue(bindsonObj[cellitem.DataContent]?.ToString());
                                    }
                                    //writeCell.SetCellValue(((JArray)data)[0][cellitem.DataContent].ToString());
                                }
                                else
                                {
                                    var bindsonObj = ((JObject)data)[cellitem.DataType];
                                    if (bindsonObj.Type == JTokenType.Array)
                                    {
                                        writeCell.SetCellValue(((JArray)bindsonObj)[0][cellitem.DataContent]?.ToString());
                                        //獲取當前行
                                    }
                                    else
                                    {
                                        writeCell.SetCellValue(bindsonObj[cellitem.DataContent]?.ToString());
                                    }
                                }
                            }
                            else//多行
                            {
                                if (data.Type == JTokenType.Array)
                                {
                                    var bindsonObj = ((JArray)data)[0][cellitem.DataType];
                                    if (bindsonObj.Type == JTokenType.Array)
                                    {

                                        if (cellitem.SourceCount < datarowindex)
                                        {
                                            writeCell.SetCellValue(((JArray)bindsonObj)[0][cellitem.DataContent]?.ToString());
                                            // writeCell.SetCellValue(((JArray)data)[0][cellitem.DataContent].ToString());
                                        }
                                        else
                                        {
                                            writeCell.SetCellValue(((JArray)bindsonObj)[datarowindex][cellitem.DataContent]?.ToString());

                                        }

                                    }
                                    else
                                    {
                                        writeCell.SetCellValue(bindsonObj[cellitem.DataContent]?.ToString());
                                    }
                                    //writeCell.SetCellValue(((JArray)data)[0][cellitem.DataContent].ToString());
                                }
                                else
                                {
                                    var bindsonObj = ((JObject)data)[cellitem.DataType];
                                    if (bindsonObj.Type == JTokenType.Array)
                                    {
                                        //獲取當前行
                                        if (cellitem.SourceCount < datarowindex)
                                        {
                                            writeCell.SetCellValue(((JArray)bindsonObj)[0][cellitem.DataContent]?.ToString());
                                            // writeCell.SetCellValue(((JArray)data)[0][cellitem.DataContent].ToString());
                                        }
                                        else
                                        {
                                            writeCell.SetCellValue(((JArray)bindsonObj)[datarowindex][cellitem.DataContent]?.ToString());

                                        }
                                    }
                                    else
                                    {
                                        writeCell.SetCellValue(bindsonObj[cellitem.DataContent]?.ToString());
                                    }
                                }
                            }
                        }
                    }

                    if (datarowindex > 0)
                        addrowCount += 1;
                }
                //addrowCount -= 1;

            }

            using (FileStream file2007 = new FileStream("d:\\test20230518" + DateTime.Now.Ticks.ToString() + ".xlsx", FileMode.Create))
            {
                workbook.Write(file2007);
                file2007.Close();
                workbook.Close();
            }

            //MemoryStream memoryStream = new MemoryStream();
            //workbook.Write(memoryStream);
            //var buf = memoryStream.ToArray();
            ////memoryStream = (MemoryStream)null;
            ////返回待下載文件
            //Stream stream = new MemoryStream(buf);
            //stream.Flush();
            //stream.Position = 0L;
            //stream.Seek(0L, SeekOrigin.Begin);
            ////string str = ".xlsx";
            //return stream;
        }

        private bool setEmpateArrayObj(JToken data,
            string datapath,
            WriteExcelDataDefine cellitem)
        {
            if (data.Type == JTokenType.Array)
            {
                var allCount = data.Count();

                return setEmpateObj(data.ElementAt(0), datapath, cellitem, allCount);
            }
            return false;
        }

        private bool setEmpateObj(JToken data,
            string datapath,
            WriteExcelDataDefine cellitem,
            int allcount=1)
        {
            if (data.Type == JTokenType.Object
                && data[datapath] != null)
            {
                cellitem.WriteMode = (byte)(allcount > 1 ? 1 : 0);
                cellitem.SourceCount = allcount;
                cellitem.MaxWriteRowCount = allcount;//多行
                return true;
            }
            return false;
        }

        private void setbindPObjects(JToken data,
            Dictionary<string, int> mTableDefines,
            IOrderedEnumerable<WriteExcelDataDefine> orderbyCells)
        {
            var bindObjName = data.GetType().Name;
            foreach (var cellitem in orderbyCells)
            {
                if (cellitem.WriteType == 5) continue;//常量跳過

                if (cellitem.WriteType == 4
                    &&
                    (setEmpateObj(data, cellitem.DataContent, cellitem)
                        || setEmpateArrayObj(data, cellitem.DataContent, cellitem)))
                {
                    continue;

                }//綁定對象

                if (cellitem.WriteType == 3)
                {
                    if (!string.IsNullOrWhiteSpace(cellitem.DataType)
                    && !string.IsNullOrWhiteSpace(cellitem.DataContent))
                    {
                        JToken sondata = null;
                        if (data.Type == JTokenType.Array
                            && data.Count() > 0)
                        {
                            sondata = ((JArray)data)[0][cellitem.DataType];
                        }
                        else if (data.Type == JTokenType.Object)
                        {
                            sondata = ((JObject)data)[cellitem.DataType];
                        }

                        if (sondata != null
                             &&
                (setEmpateObj(sondata, cellitem.DataContent, cellitem)
                    || setEmpateArrayObj(sondata, cellitem.DataContent, cellitem)))
                        {
                            continue;
                        }

                    }

                    cellitem.DataType = "";
                    cellitem.DataContent = "";
                    cellitem.WriteType = 5;
                    cellitem.WriteMode = 0;
                    cellitem.SourceCount = 1;
                    cellitem.MaxWriteRowCount = 1;//多行
                }//子對象

            }
        }

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章