在 EPPlus 导出中检测数据表日期字段和强制日期格式

Detect datatable date field and force date format in EPPlus export

我的页面上有一个按钮,单击该按钮可将数据从 gridview 导出到 excel。

protected void btExport_Click(object sender, EventArgs e)
{
    Response.Clear();
    Response.Charset = "";
    Response.ContentEncoding = System.Text.Encoding.UTF8;
    Response.Cache.SetCacheability(HttpCacheability.NoCache);
    Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    Response.AddHeader("content-disposition", "attachment;filename=Output.xlsx");

    DataTable dt= gvOutput.DataSource as DataTable;

    ExcelPackage pck = new ExcelPackage();
    using(pck)
    {
      ExcelWorksheet wsDt = pck.Workbook.Worksheets.Add("Sheet1");
      wsDt.Cells["A1"].LoadFromDataTable(dt, true, TableStyles.None);
      wsDt.Cells[wsDt.Dimension.Address].AutoFitColumns();

      Response.BinaryWrite(pck.GetAsByteArray());

    }

    Response.Flush();
    Response.End();
}

使用上面的代码可以正常工作,但是日期字段被格式化为整数。我知道可以强制特定单元格具有特定格式,但我的问题是日期列会随着 gridview 的数据集是动态的而改变。

我需要一种方法来即时识别哪一列是日期并强制该列的格式为日期时间。

我想它会涉及这样的 IF 语句,但我不知道要放入什么或放在哪里!

if (dt.Columns[x].DataType == typeof(DateTime))
{ 
    //do something
}

非常感谢ideas/help。

遍历 DataTable 列并确定哪些是 DateTime 值。如果找到一个,则设置列的格式,如下所示。我没有测试代码,但应该是遵循的一般逻辑。

...
wsDt.Cells["A1"].LoadFromDataTable(dt, true, TableStyles.None);
int colNumber = 1;

foreach (DataColumn col in dt.Columns) 
{        
    if (col.DataType == typeof(DateTime))
    { 
         wsDt.Column(colNumber).Style.Numberformat.Format = "MM/dd/yyyy hh:mm:ss AM/PM";
    }    
    colNumber++;      
}

wsDt.Cells[wsDt.Dimension.Address].AutoFitColumns();
Response.BinaryWrite(pck.GetAsByteArray());

对上述答案稍作修改。几乎正确。我用下面的代码修复了它。

wsDt.Cells["A1"].LoadFromDataTable(dt, true, TableStyles.None);

int colNumber = 0;
foreach (DataColumn col in dt.Columns) 
{
    colNumber++;
    if (col.DataType == typeof(DateTime))
    { 
       wsDt.Column(colNumber).Style.Numberformat.Format = "mm/dd/yyyy hh:mm:ss AM/PM"
    }          
}

wsDt.Cells[wsDt.Dimension.Address].AutoFitColumns();
Response.BinaryWrite(pck.GetAsByteArray());

如果我错了请纠正我,但我相信@desiguy 和@Rick S 的回答并不完全正确。

在@desiguy 的回答 中,语句colNumber++ 在数据表列的foreach 循环之外。

因此,因为索引增量是在循环外完成的,所以循环将始终在colNumber=1.

上进行

关于@Rick S 的解决方案;如果我没记错的话,在 EPPlus 中,列索引以 1 而不是 0 开头,所以,语句:

wsDt.Column(colNumber++).Style.Numberformat.Format = "mm/dd/yyyy hh:mm:ss AM/PM"

应该如下:

wsDt.Column(++colNumber).Style.Numberformat.Format = "MM/dd/yyyy hh:mm:ss AM/PM"

虽然有 两个 差异:

  1. colNumber++改为++colNumber。在这种情况下,该列将以 1 而不是 0 开头,因此您不会收到错误

  2. mm/dd/yyyy 改为 MM/dd/yyyy 因为小写的 mm 代表分钟而不是月,因此 MM 是正确的语法代表月份

另一个更简单的解决方案是仅将 int colNumber = 0; 设置为 int colNumber = 1;,您会得到相同的结果。

完全更正(和测试)的代码:

        int colNumber = 0;

        foreach (DataColumn col in DataToExport.Columns)
        {
            colNumber++;
            if (col.DataType == typeof(DateTime))
            {
                wsDt.Column(colNumber).Style.Numberformat.Format = "MM/dd/yyyy hh:mm:ss AM/PM";
            }
        }