NPOI导出EXCEL模板文件联动的效果

第一步:先定义下拉的数据源,正常情况是在建立第二个sheet,第一个sheet作为主界面显示,而下拉数据源放在后面

定义数据源根据父子关系建立,如

此处cell的操作需要根据父子表的关系循环设置

            DataTable dtF = ds.Tables[0]; //父
            DataTable dtC = ds.Tables[1]; //子
            ISheet sheetSource = hssfworkbook.CreateSheet("Dictionary");
            int MaxRow = dtBusiness.Rows.Count;//默认最大行数
            if (dtF != null && dtF.Rows.Count > 0)
            {
                for (int i = 0; i < dtF.Rows.Count; i++)
                {
                    var row = sheet2.CreateRow(i);//添加行
                    row.CreateCell(0).SetCellValue(dtF.Rows[i]["Name"].ToString());
                    if (i == 0)
                    {
                        for (int j = 1; j <= dtF.Rows.Count; j++)
                        {
                            row.CreateCell(j).SetCellValue(dtF.Rows[j - 1]["Name"].ToString());
                        }
                    }
                }
                for (int i = 1; i <= dtF.Rows.Count; i++)
                {
                    DataRow[] dr = dtC.Select("PCode='" + dtF.Rows[i - 1]["Code"].ToString() + "'");
                    if (dr.Length > 0) 
                    {
                        if (dr.Length > MaxRow)
                        {
                            int needLen = dr.Length - MaxRow;
                        }
                        for (int j = 1; j <= dr.Length; j++)
                        {
                            if (j < MaxRow)
                            {
                                var r = sheetSource.GetRow(j);//针对已经存在行的情况下
                                r.CreateCell(i).SetCellValue(dr[j - 1]["Name"].ToString());
                            }
                            else
                            {
                                var newRow = sheetSource.CreateRow(j);//添加行
                                newRow.CreateCell(i).SetCellValue(dr[j - 1]["Name"].ToString());
                                MaxRow++;
                            }
                        }
                    }
                }
            }

 数字转字母的方法,为了匹配出列名,其实不需要也可以,因为模板都是固定格式的,可以直接写入自己需要的列名,如A,B...

 private string GetExcelColumnName(int columnNumber)
 {
    int dividend = columnNumber;
    string columnName = String.Empty;
    int modulo;
    while (dividend > 0)
    {
        modulo = (dividend - 1) % 26;
        columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
        dividend = (int)((dividend - modulo) / 26);
    }
    return columnName;
  }

第二步:设置主菜单下拉选项

IName range = hssfworkbook.CreateName();
range.NameName = "MainRange";
var colName = GetExcelColumnName(1);//数字转成大写英文字母,就是列头
range.RefersToFormula = string.Format("{0}!${3}${2}:${3}${1}", "Dictionary", dtF.Rows.Count.ToString(), 1, colName);//动态设定范围
DVConstraint constraint = DVConstraint.CreateFormulaListConstraint("MainRange");
HSSFDataValidation dataValidate = new HSSFDataValidation(regions, constraint);
sheet.AddValidationData(dataValidate); //sheet 是已经新建好的第一个sheet

第三步: 定义公式名称(EXCEL里的定义名词)

for (int i = 1; i <= dtF.Rows.Count; i++)
{
     IName rangeC = hssfworkbook.CreateName();
     rangeC.NameName = dtF.Rows[i - 1]["Name"].ToString();
     var colNameC = GetExcelColumnName(i+1);
     DataRow[] dr = dtC.Select("PCode='" + dtF.Rows[i - 1]["Code"].ToString() + "'");
     rangeC.RefersToFormula = string.Format("{0}!${3}$2:${3}${1}", "Dictionary", dr.Length+1, 2, colNameC);//动态设定范围
}

第二步与第三部关键点在于设置校验的范围

第四步:加入验证

for (int i = 1; i <= 2; i++) //2表示控制2列,其实可以根据这个思路随意扩展
{
    var smallColIndex = i - 1;
    colName = GetExcelColumnName(1);
    for (int j = 1; j <= 50; j++) //设置多少行应用这个验证
    {
       CellRangeAddressList regions2 = new CellRangeAddressList(j, j, smallColIndex, smallColIndex);
       DVConstraint constraint2 = DVConstraint.CreateFormulaListConstraint(string.Format("INDIRECT(${0}${1})", colName, j + 1));//将父值关联起来
       HSSFDataValidation dataValidate2 = new HSSFDataValidation(regions2, constraint2);
       sheet.AddValidationData(dataValidate2);
    }
}

最终效果,选择一级,二级根据一级选项产生联动效果

 其实实现这个效果还是先要会EXCEL里这样的操作,这样更容易理解EXCEL里公式

         

猜你喜欢

转载自www.cnblogs.com/zjy/p/9975720.html