zoukankan      html  css  js  c++  java
  • GridView合并单元格及导出至Excel

    #region GridView合并矩形单元格
        /// <summary>
        /// 合并成为矩形单元格
        /// </summary>
        /// <param name="GridView1"></param>
        /// <param name="sRow">开始行索引</param>
        /// <param name="sCol">开始列索引</param>
        /// <param name="eRow">结束行索引</param>
        /// <param name="eCol">结束列索引</param>
        public static void GroupRectangle(GridView GridView1, int sRow, int sCol, int eRow, int eCol)
        {
            if (sRow < 0 || sRow > eRow || eRow > GridView1.Rows.Count - 1)
            {
                return;
            }
            if (sCol < 0 || sCol > eCol || eCol > GridView1.Columns.Count - 1)
            {
                return;
            }
            TableCell oldTc = GridView1.Rows[sRow].Cells[sCol];
            oldTc.ColumnSpan = eCol - sCol + 1;
            oldTc.RowSpan = eRow - sRow + 1;
            //oldTc.ColumnSpan = eCol - sCol > 0 ? eCol - sCol : 1;
            //oldTc.RowSpan = eRow - sRow > 0 ? eRow - sRow : 1;
            for (int i = sRow; i <= eRow; i++)
            {
                for (int j = sCol; j <= eCol; j++)
                {
                    if (i == sRow && j == sCol)//起始单元格
                    {
                        //oldTc.ColumnSpan = 1;
                        //oldTc.RowSpan = 1;
                        continue;
                    }
    
                    TableCell tc = GridView1.Rows[i].Cells[j];
                    tc.Visible = false;
                }
            }
            oldTc.Visible = true;
            oldTc.VerticalAlign = VerticalAlign.Middle;
            oldTc.HorizontalAlign = HorizontalAlign.Center;
        }
        #endregion

    所有生成的Excel文件均包含了单元格合并的信息

    #region GridView数据导出为,该方法未导出的Excel与纯正Excel相差较大,且在数据量较大时会出现内存溢出
    
        /// <summary>
        /// XmlDocument转换xml文件
        /// </summary>
        /// <param name="gv"></param>
        /// <param name="filePath">Server.MapPath("bookstore.xml")</param>
        public void ToXMLMethod1(GridView gv, string filePath)
        {
            XmlText xmlText;
            XmlDocument xmlDoc = new XmlDocument();
    
            //加入XML的声明段落
            XmlNode xmlNode = xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", null);
            xmlDoc.AppendChild(xmlNode);
    
            //添加一个根元素
            XmlElement xmlTable = xmlDoc.CreateElement("", "table", string.Empty);
            xmlText = xmlDoc.CreateTextNode("");
            xmlTable.AppendChild(xmlText);
            xmlDoc.AppendChild(xmlTable);
    
    
            //添加了自定义表头
            if (gv.HeaderRow.Cells.Count > 0)
            {
                TableCellCollection cellCollection = gv.HeaderRow.Cells;
    
    
                XmlElement xmlHeader = xmlDoc.CreateElement("", "tr", string.Empty);
                xmlText = xmlDoc.CreateTextNode("");
                xmlHeader.AppendChild(xmlText);
                xmlDoc.ChildNodes.Item(1).AppendChild(xmlHeader);
                for (int i = 0; i < gv.HeaderRow.Cells.Count; i++)
                {
                    XmlElement xmlTd = xmlDoc.CreateElement("", "td", string.Empty);
                    xmlText = xmlDoc.CreateTextNode(cellCollection[i].Text);
                    xmlTd.AppendChild(xmlText);
                    xmlTd.SetAttribute("RowSpan", gv.HeaderRow.Cells[i].RowSpan.ToString());
                    xmlTd.SetAttribute("ColumnSpan", gv.HeaderRow.Cells[i].ColumnSpan.ToString());
                    xmlDoc.ChildNodes.Item(1).AppendChild(xmlHeader).AppendChild(xmlTd);
                }
            }
    
    
    
            for (int i = 0; i < gv.Rows.Count; i++)
            {
                //加入子元素tr
                XmlElement xmlTr = xmlDoc.CreateElement("", "tr", string.Empty);
                xmlText = xmlDoc.CreateTextNode("");
                xmlTr.AppendChild(xmlText);
                xmlDoc.ChildNodes.Item(1).AppendChild(xmlTr);
    
                for (int j = 0; j < gv.Rows[i].Cells.Count; j++)
                {
                    TableCell cell = gv.Rows[i].Cells[j];
    
                    XmlElement xmlTd = xmlDoc.CreateElement("", "td", string.Empty);
                    xmlText = xmlDoc.CreateTextNode(cell.Text);
                    xmlTd.AppendChild(xmlText);
                    xmlTd.SetAttribute("RowSpan", cell.RowSpan.ToString());
                    xmlTd.SetAttribute("ColumnSpan", cell.ColumnSpan.ToString());
                    xmlDoc.ChildNodes.Item(1).AppendChild(xmlTr).AppendChild(xmlTd);
                }
            }
    
            xmlDoc.Save(filePath); //保存 
        }
        #endregion

    为改善上一段代码出现的内存溢出问题,修改为每次添加语句直接写入XML文件

    #region 将GridView中的数据导出为Xml文件
    
        /// <summary>
        /// 将GridView中的数据导出为Xml文件
        /// </summary>
        /// <param name="gv">需要处理的GridView</param>
        /// <param name="filePath">xml文件存放路径</param>
        public static void ToXml(GridView gv, string filePath)
        {
    
            FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite);
            StreamWriter sw = new StreamWriter(fs);
    
            #region 添加xml头 并指定excel打开
    
            string xmlStr = "<?xml version='1.0'?>" +//xml头文件
    "<?mso-application progid='Excel.Sheet'?>" +//默认以Excel打开
    "<Workbook xmlns='urn:schemas-microsoft-com:office:spreadsheet' " +
     "xmlns:o='urn:schemas-microsoft-com:office:office' " +
     "xmlns:x='urn:schemas-microsoft-com:office:excel' " +
     "xmlns:ss='urn:schemas-microsoft-com:office:spreadsheet' " +
     "xmlns:html='http://www.w3.org/TR/REC-html40'>";
    
            xmlStr += "<DocumentProperties xmlns='urn:schemas-microsoft-com:office:office'></DocumentProperties>" +
     "<OfficeDocumentSettings xmlns='urn:schemas-microsoft-com:office:office'></OfficeDocumentSettings>" +
     "<ExcelWorkbook xmlns='urn:schemas-microsoft-com:office:excel'></ExcelWorkbook>" +
     "<Styles> " +
     "<Style ss:ID='Default' ss:Name='Normal'>" +
         "<Alignment ss:Vertical='Center' ss:Horizontal='Center'/>" +
            "<Borders/>" +
            "<Font ss:FontName='宋体' x:CharSet='134' ss:Size='11' ss:Color='#000000'/><Interior/>" +
       "<NumberFormat/>" +
       "<Protection/>" +
      "</Style>" +
          "</Styles>";
    
    
            sw.Write(xmlStr);
            xmlStr = string.Empty;
    
            #endregion
    
            //新建工作表
            xmlStr += "<Worksheet ss:Name='Sheet1'>";
            //新建表格
            xmlStr += "<Table x:FullColumns='1' x:FullRows='1' ss:DefaultColumnWidth='54' ss:DefaultRowHeight='13.5'>";
    
            sw.WriteLine(xmlStr);
            xmlStr = string.Empty;
    
            /***************************************/
            /***************添加表头****************/
            /***************************************/
            string a1 = "";
            xmlStr += "<Row>";
            for (int i = 0; i < gv.HeaderRow.Cells.Count; i++)
            {
                a1 += "<tr><th>" + gv.HeaderRow.Cells[i].Text;
                xmlStr += "<Cell ";
                TableCell cell = gv.HeaderRow.Cells[i];
    
                //跨列属性可能为添加了html属性colspan,也可能是由cell的ColumnSpan属性指定
                int colSpan = -1;
                if (cell.Attributes["colspan"] != null && cell.Attributes["colspan"] != string.Empty)
                {
                    colSpan = int.Parse(cell.Attributes["colspan"].ToString());
                }
                if (cell.ColumnSpan > 1)
                {
                    colSpan = cell.ColumnSpan;
                }
                if (colSpan > 0)
                {
                    colSpan--;
                    xmlStr += "ss:MergeAcross='" + colSpan.ToString() + "'";
                }
                xmlStr += " ><Data ss:Type='String'>";
                string strHeader = gv.HeaderRow.Cells[i].Text;
    
                if (strHeader.Contains("</th></tr><tr>"))//换行标记
                {
                    xmlStr += strHeader.Substring(0, strHeader.Length - 14) + "</Data></Cell></Row><Row>";
                }
                else
                {
                    xmlStr += strHeader + "</Data></Cell>";
                }
            }
            xmlStr += "</Row>";
    
    
            sw.WriteLine(xmlStr);
            xmlStr = string.Empty;
    
            /***************************************/
            /***************添加数据****************/
            /***************************************/
    
            int rowCount = gv.Rows.Count;
    
            //gv.HeaderRow.Cells.Count属性始终为0,可能为控件bug。循环控件表头遍历出列数
            int colCOunt = 0;
            foreach (TableCell cell in gv.HeaderRow.Cells)
            {
                if (cell.Text.Contains("</th></tr><tr>"))
                {
                    colCOunt = 0;
                    continue;
                }
                else
                {
                    colCOunt++;
                }
            }
    
            for (int i = 0; i < rowCount; i++)
            {
                xmlStr += "<Row>";
    
                bool flagPreviousVisible = true;
                for (int j = 0; j < colCOunt; j++)
                {
                    if (gv.Rows[i].Cells[j].Visible == false)
                    {
                        flagPreviousVisible = false;
                        continue;
                    }
    
                    #region 判断是否为矩形单元格中的单元格
    
                    if (i > 0 && j > 0)
                    {
                        bool flagSkip = false;
                        int tempx = -1;//记录矩形单元格的左下角位置
                        for (int l = j - 1; l >= 0; l--)
                        {
                            if (gv.Rows[i].Cells[l].Visible == false)
                            {
                                tempx = l;
                                break;
                            }
                            else
                            {
                                continue;
                            }
                        }
                        if (tempx > -1)//存在可能的矩形单元格
                        {
                            for (int m = i - 1; m >= 0; m--)
                            {
                                int colSpan = j - tempx + 1;
                                int rowSpan = i - m + 1;
                                if (gv.Rows[m].Cells[tempx].ColumnSpan >= colSpan && gv.Rows[m].Cells[tempx].RowSpan >= rowSpan)//存在矩形单元格,即当前单元格属于矩形单元格中的一部分
                                {
                                    flagPreviousVisible = false;//模拟前一单元格不可见(为添加Index属性)
                                    flagSkip = true;
                                    break;//满足条件,跳出循环
                                }
                                else
                                {
                                    continue;
                                }
                            }
                        }
                        if (flagSkip)//存在矩形单元格,且该单元格存在于该矩形单元格,跳过此单元格拼接字符串
                        {
                            continue;
                        }
                    }
    
                    #endregion
    
                    int MergeAcross = gv.Rows[i].Cells[j].ColumnSpan;//跨列,即合并的列数
                    int MergeDown = gv.Rows[i].Cells[j].RowSpan;//跨行,即合并的行数
    
                    xmlStr += "<Cell ";
    
                    if (MergeAcross > 0)//存在要合并的行
                    {
                        xmlStr += "ss:MergeAcross='" + --MergeAcross + "' ";//ss:MergeAcross 合并列 
                    }
                    if (MergeDown > 0)//存在要合并的列
                    {
                        xmlStr += "ss:MergeDown='" + --MergeDown + "' ";//ss:MergeDown 合并行
                    }
    
    
                    if (flagPreviousVisible == false)
                    {
                        int a = j + 1;
                        xmlStr += "ss:Index='" + a + "' ";
                        flagPreviousVisible = true;
                    }
                    xmlStr += " >";
                    xmlStr += "<Data ss:Type='String'>" + gv.Rows[i].Cells[j].Text + "</Data>";//
                    xmlStr += "</Cell>";
                }
                xmlStr += "</Row>";
    
                sw.WriteLine(xmlStr);
                xmlStr = string.Empty;
            }
    
            xmlStr += "</Table>";
    
            sw.WriteLine(xmlStr);
            xmlStr = string.Empty;
    
            #region 添加xml打印格式等属性,完成xml字符串拼接
    
            //WorksheetOptions主要定义 打印方式  边距 窗口冻结 等等 ,在设计 Excel文件时都设置好了  不需要修改
            xmlStr += "<WorksheetOptions xmlns='urn:schemas-microsoft-com:office:excel'>" +
       "<PageSetup>" +
        "<Header x:Margin='0.3'/>" +
        "<Footer x:Margin='0.3'/>" +
        "<PageMargins x:Bottom='0.75' x:Left='0.7' x:Right='0.7' x:Top='0.75'/>" +
       "</PageSetup>" +
       "<Print>" +
        "<ValidPrinterInfo/>" +
        "<PaperSizeIndex>9</PaperSizeIndex>" +
        "<HorizontalResolution>200</HorizontalResolution>" +
        "<VerticalResolution>200</VerticalResolution>" +
       "</Print>" +
       "<Selected/>" +
                /*
                 * 
                 *这段代码加载<Selected>标签之后,用于冻结窗口
                 * 
                 * <FreezePanes/>
                 * <FrozenNoSplit/>
                 * <SplitHorizontal>3</SplitHorizontal>//冻结的窗口行数             
                 * <ActivePane>2</ActivePane>
                 *                                        
                 */
    
       "<Panes>" +
        "<Pane>" +
         "<Number>3</Number>" +
         "<ActiveRow>2</ActiveRow>" +
         "<RangeSelection>R3C1:R4C1</RangeSelection>" +
        "</Pane>" +
       "</Panes>" +
       "<ProtectObjects>False</ProtectObjects>" +
       "<ProtectScenarios>False</ProtectScenarios>" +
      "</WorksheetOptions>";
            xmlStr += "</Worksheet>";
            xmlStr += "</Workbook>";
    
            #endregion
    
            sw.Write(xmlStr);
            xmlStr = string.Empty;
    
            sw.Close();
            fs.Close();
    
            //XmlDocument xmldoc = new XmlDocument(); //创建空的XML文档
            //xmldoc.LoadXml(xmlStr);
            //xmldoc.Save(Server.MapPath("temp.xml")); //保存 
        }
    
    
        #endregion

    使用第三方插件NPOI生成真正Excel文件

    #region 将GridView中的数据导出为Xml文件 表头部分待完善
    
        /// <summary>
        /// 将GridView中的数据导出为Xml文件
        /// </summary>
        /// <param name="gv">需要处理的GridView</param>
        /// <param name="filePath">xml文件存放路径</param>
        public static void ToXml(GridView gv, string filePath)
        {
            IWorkbook hssfworkbook = new HSSFWorkbook();
            ISheet sheet = hssfworkbook.CreateSheet("sheet1");
    
            IRow row = sheet.CreateRow(0);
            ICell cell;
    
            ICellStyle cellStyle = hssfworkbook.CreateCellStyle();
            cellStyle.Alignment = HorizontalAlignment.CENTER_SELECTION;
            cellStyle.VerticalAlignment = VerticalAlignment.CENTER;
    
            int colCount = 0;//记录GridView列数
            int rowInex = 0;//记录表头的行数
    
            /***************************************/
            /***************添加表头****************/
            /***************************************/
    
            #region 添加表头
    
            int groupCount = 0;//记录分组数
            int colIndex = 0;//记录列索引,并于结束表头遍历后记录总列数
            for (int i = 0; i < gv.HeaderRow.Cells.Count; i++)
            {
                if (rowInex != groupCount)//新增了标题行时重新创建
                {
                    row = sheet.CreateRow(rowInex);
                    groupCount = rowInex;
                }
    
                #region 是否跳过当前单元格
    
                for (int m = 0; m < sheet.NumMergedRegions; m++)//遍历所有合并区域
                {
                    NPOI.SS.Util.CellRangeAddress a = sheet.GetMergedRegion(m);
                    //当前单元格是处于合并区域内
                    if (a.FirstColumn <= colIndex && a.LastColumn >= colIndex
                        && a.FirstRow <= rowInex && a.LastRow >= rowInex)
                    {
                        colIndex++;
                        m = 0;//重新遍历所有合并区域判断新单元格是否位于合并区域
                    }
                }
                
    
                #endregion
    
                cell = row.CreateCell(colIndex);
                cell.CellStyle = cellStyle;
    
                TableCell tablecell = gv.HeaderRow.Cells[i];
    
                //跨列属性可能为添加了html属性colspan,也可能是由cell的ColumnSpan属性指定
                int colSpan = 0;
                int rowSpan = 0;
    
                #region 获取跨行跨列属性值
                //跨列
                if (!string.IsNullOrEmpty(tablecell.Attributes["colspan"]))
                {
                    colSpan = int.Parse(tablecell.Attributes["colspan"].ToString());
                    colSpan--;
                }
                if (tablecell.ColumnSpan > 1)
                {
                    colSpan = tablecell.ColumnSpan;
                    colSpan--;
                }
    
                //跨行
                if (!string.IsNullOrEmpty(tablecell.Attributes["rowSpan"]))
                {
                    rowSpan = int.Parse(tablecell.Attributes["rowSpan"].ToString());
                    rowSpan--;
                }
                if (tablecell.RowSpan > 1)
                {
                    rowSpan = tablecell.RowSpan;
                    rowSpan--;
                }
                #endregion
    
                //添加excel合并区域
                if (colSpan > 0 || rowSpan > 0)
                {
                    sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(rowInex, rowInex + rowSpan, colIndex, colIndex + colSpan));
                    colIndex += colSpan + 1;//重新设置列索引
                }
                else
                {
                    colIndex++;
                }
                string strHeader = gv.HeaderRow.Cells[i].Text;
    
                if (strHeader.Contains("</th></tr><tr>"))//换行标记,当只存在一行标题时不存在</th></tr><tr>,此时colCount无法被赋值
                {
                    rowInex++;
                    colCount = colIndex;
                    colIndex = 0;
    
                    strHeader = strHeader.Substring(0, strHeader.IndexOf("</th></tr><tr>"));
                }
                cell.SetCellValue(strHeader);
            }
            if (groupCount == 0)//只有一行标题时另外为colCount赋值
            {
                colCount = colIndex;
            }
    
            #endregion
    
            rowInex++;//表头结束后另起一行开始记录控件数据行索引
    
            /***************************************/
            /***************添加数据****************/
            /***************************************/
    
            #region 添加数据
    
            int rowCount = gv.Rows.Count;
    
            for (int i = 0; i < rowCount; i++)
            {
                row = sheet.CreateRow(rowInex);
    
                //bool flagPreviousVisible = true;
                for (int j = 0; j < colCount; j++)
                {
                    if (gv.Rows[i].Cells[j].Visible == false)
                    {
                        //flagPreviousVisible = false;
                        continue;
                    }
    
                    #region 判断是否为矩形单元格中的单元格
    
                    if (i > 0 && j > 0)
                    {
                        bool flagSkip = false;
                        int tempx = -1;//记录矩形单元格的左下角位置
                        for (int l = j - 1; l >= 0; l--)
                        {
                            if (gv.Rows[i].Cells[l].Visible == false)
                            {
                                tempx = l;
                                break;
                            }
                            else
                            {
                                continue;
                            }
                        }
                        if (tempx > -1)//存在可能的矩形单元格
                        {
                            for (int m = i - 1; m >= 0; m--)
                            {
                                int colSpan = j - tempx + 1;
                                int rowSpan = i - m + 1;
                                if (gv.Rows[m].Cells[tempx].ColumnSpan >= colSpan && gv.Rows[m].Cells[tempx].RowSpan >= rowSpan)//存在矩形单元格,即当前单元格属于矩形单元格中的一部分
                                {
                                    flagSkip = true;
                                    break;//满足条件,跳出循环
                                }
                                else
                                {
                                    continue;
                                }
                            }
                        }
                        if (flagSkip)//存在矩形单元格,且该单元格存在于该矩形单元格,跳过此单元格拼接字符串
                        {
                            continue;
                        }
                    }
    
                    #endregion
    
    
                    cell = row.CreateCell(j);
                    cell.CellStyle = cellStyle;
                    cell.SetCellType(CellType.STRING);
                    if (!string.IsNullOrEmpty(gv.Rows[i].Cells[j].Text))
                    {
    
                        cell.SetCellValue(gv.Rows[i].Cells[j].Text);
                    }
                    else
                    {
                        cell.SetCellValue(" ");
                    }
    
    
                    int MergeAcross = gv.Rows[i].Cells[j].ColumnSpan;//跨列,即合并的列数
                    if (MergeAcross > 0)
                    {
                        MergeAcross--;
                    }
                    else
                    {
                        MergeAcross = 0;
                    }
                    //? MergeAcross = MergeAcross - 1 : MergeAcross = 0;
                    int MergeDown = gv.Rows[i].Cells[j].RowSpan;//跨行,即合并的行数
                    //MergeDown > 0 ? MergeDown-- : MergeDown = 0;
                    if (MergeDown > 0)
                    {
                        MergeDown--;
                    }
                    else
                    {
                        MergeDown = 0;
                    }
    
                    if (MergeAcross > 0 || MergeDown > 0)//存在要合并的行
                    {
                        sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(rowInex, rowInex + MergeDown, j, j + MergeAcross));
                        j += MergeAcross;
                        //colCount += 1;
                    }
    
    
                    FileStream fs = new FileStream(filePath, FileMode.Create);
                    hssfworkbook.Write(fs);
                    fs.Close();
                }
                rowInex++;
            }
    
            #endregion
        }
    
    
        #endregion     
    View Code
  • 相关阅读:
    《人类简史》八、融合统一(下)——宗教的法则、历史的混沌
    《今日简史》七、融合统一(中)——帝国的愿景
    《人类简史》六、融合统一(上)——历史的方向、金钱的味道
    《人类简史》五、监狱高墙——想象构建的秩序
    设计模式之职责链模式(Chain of Responsibility)
    设计模式之代理模式(Proxy)
    设计模式之享元模式(FlyWeight)
    设计模式之外观模式(Facade)
    设计模式之装饰模式(Decorator)
    设计模式之组合模式(Composite)
  • 原文地址:https://www.cnblogs.com/candr/p/3873490.html
Copyright © 2011-2022 走看看