【问题标题】:Excel Interop cell formatting of Dates日期的 Excel 互操作单元格格式
【发布时间】:2013-03-24 19:44:11
【问题描述】:

我的程序在 Excel 中创建一个输出。

有些日期似乎被误解了:

打开文件时,日期是屏幕截图中的混合日期。
如果我实际上将光标放在 Excel 的计算框中(在屏幕打印中)并按 Enter,则单元格的格式将恢复为正确的格式。

我正在使用Microsoft.Office.Interop.Excel 将数据从Datatable 移动到保存在我的解决方案中的Excel 模板。

在将数据放入单元格之前,我使用switch 相应地更改每列的数字格式:

for(int i = 1; i < NumColumns + 1; i++) {
    switch(dt.Columns[i-1].DataType.ToString()) {
        case "System.Int32":
            xlWorkSheet.Columns[i].NumberFormat = "#,##0_ ;[Red]-#,##0 ";
            break;
        case "System.String":
            xlWorkSheet.Columns[i].NumberFormat = "@";
            break;
        case "System.DateTime":
            xlWorkSheet.Columns[i].NumberFormat = "[$-809]dd mmmm yyyy;@"; //"dd-mmm-yy";
            break;
        case "System.Date":
            xlWorkSheet.Columns[i].NumberFormat = "[$-809]dd mmmm yyyy;@"; //"dd-mmm-yy";
            break;
        default:
            xlWorkSheet.Columns[i].NumberFormat = "@";
            break;
    }
}

要从数据表中移动值,我使用嵌套循环:

//move header totals into the spreadsheet
for(int i = 1; i < NumColumns + 1; i++) {
    xlWorkSheet.Cells[1, i].value = dt.Columns[i - 1].ColumnName;
}

//move in the data
DataView dv = new DataView(dt);
dv.Sort = "Date ASC";

int rowCount = 2;
string theValue;
try {
    foreach(DataRowView dr in dv) {//(DataRow dr indt.Rows)
        for(int i = 1; i < NumColumns + 1; i++) {
            theValue = dr[i - 1].ToString();
            xlWorkSheet.Cells[rowCount, i].value = theValue;
        }
        rowCount += 1;
    }
} catch(Exception) {
    throw;
}

在存储过程中,当我填充数据表时,我尝试使用 DATETIME 和以下内容明确拼写类型:

SELECT 
"Date" = CONVERT(DATE,b.[Date])
    ...

如何使我的日期数据如此明确,以使 Excel 不会误解并应用所有所需的格式?


编辑

嵌套循环的下一个(未经测试的)尝试如下:

int rowCount = 2;
string theValue;
DateTime dtm;
DateTime d;
try {
    foreach(DataRowView dr in dv) {//(DataRow dr indt.Rows)
        for(int i = 1; i < NumColumns + 1; i++) {
            //theValue = dr[i - 1].ToString();
            //xlWorkSheet.Cells[rowCount, i].value = theValue;
            switch(dr[i - 1].GetType().ToString()) {
                case "System.DateTime":
                    dtm = Convert.ToDateTime(dr[i - 1]);
                    xlWorkSheet.Cells[rowCount, i].value = dtm.ToOADate();
                    break;
                case "System.Date":
                    d = Convert.ToDateTime(dr[i - 1]);
                    xlWorkSheet.Cells[rowCount, i].value = d.ToOADate();
                    break;
                default:
                    theValue = dr[i - 1].ToString();
                    xlWorkSheet.Cells[rowCount, i].value = theValue;
                    break;
            }

        }
        rowCount += 1;
    }
} catch(Exception) {
    throw;
}

【问题讨论】:

    标签: c# sql-server excel


    【解决方案1】:

    这里的问题是您将所有内容都以字符串形式写入 Excel,而 Excel 将按原样存储。在编辑并按 Enter 时,Excel 将重新解释单元格内容,然后可能会以不同的方式存储它。

    当您在 DateTime 上调用 ToString() 时,默认格式为 DD/MM/YY HH:mm:ss 格式,这正是您在结果文件中看到的内容。

    Excel 中的日期存储为表示自 1900 年以来经过的天数的数字。要获取此数字,您可以调用 ToOADate() 方法。

    http://msdn.microsoft.com/en-gb/library/system.datetime.tooadate.aspx

    将数据集设置为double 和适当的格式字符串,您应该会得到您希望的结果!

    【讨论】:

    • ...+1 对此表示感谢:我是否应该在测试datatype 的嵌套循环内实现switch;如果是日期时间,则使用 ToOADate() ;如果是字符串,则使用ToString() 等?
    • 是的,可以。另外,我认为DataRow 索引器(例如dr[i-1])会根据列类型为您输入。所以你应该能够测试返回对象(例如if (value is DateTime) 并在上面调用ToOADate()
    • ... 好的 - 我将使用新的嵌套循环编辑我的 OP - 我还没有测试它,我感觉有点在黑暗中;所以不要笑!
    【解决方案2】:

    只需将(字符串)替换为(格式化值)

    【讨论】:

    • 这不起作用,因为 Excel 将使用不同的语言环境将字符串重新解释为日期(因此设置日期 01/09/2017 可以通过 Excel 认为它是 09/01 /2017)
    猜你喜欢
    • 1970-01-01
    • 2011-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多