为啥将数据导出到 Excel 时日期格式会发生变化?

Posted

技术标签:

【中文标题】为啥将数据导出到 Excel 时日期格式会发生变化?【英文标题】:Why Date format gets change while exporting data to Excel?为什么将数据导出到 Excel 时日期格式会发生变化? 【发布时间】:2019-12-01 15:48:56 【问题描述】:

我正在处理窗口表单应用程序。在我的表单中,我有 GridView,其中有一列类型为日期。日期列的日期格式为 dd-MM-YYYY。我正在将此数据导出到 Excel 中。但问题是日期格式在 Excel 中会发生变化。

这是我将数据导出到 Excel 时的代码

    private void btnSaveDetails_Click(object sender, EventArgs e)
    

        Microsoft.Office.Interop.Excel._Application app = new Microsoft.Office.Interop.Excel.Application();
        Microsoft.Office.Interop.Excel._Workbook workbook = app.Workbooks.Add(Type.Missing);
        Microsoft.Office.Interop.Excel._Worksheet worksheet = null;
        app.Visible = true;
        worksheet = workbook.ActiveSheet;
        for (int i = 1; i < dataGridViewDetails.Columns.Count + 1; i++)
        
            worksheet.Cells[1, i] = dataGridViewDetails.Columns[i - 1].HeaderText;
         
        for (int i = 0; i < dataGridViewDetails.Rows.Count; i++)
        
            for (int j = 0; j < dataGridViewDetails.Columns.Count; j++)
            
                if (j == 3)
                
                    worksheet.Cells[i + 2, j + 1] = dataGridViewDetails.Rows[i].Cells[j].Value.ToString().Split (' ')[0];

                
                else
                
                    worksheet.Cells[i + 2, j + 1] = dataGridViewDetails.Rows[i].Cells[j].Value.ToString();
                
            
        

    

正如您在代码中看到的,我正在以字符串格式导出每个数据,因此 Excel 单元格类型应该没有问题。但数据格式仍然可以转换。我在做什么错?

【问题讨论】:

因为 Excel 设置以 wich 格式显示它应该显示这个。 只要我将每个数据都转换成字符串类型。字符串类型也有关系吗? @克里斯托弗 网格的格式仅用于显示日期。当您调用ToString 时,它只会使用默认格式。这是因为格式是网格列的一部分,而 DateTime 对象不包含格式。 【参考方案1】:

这里有两个非常不同的东西:

    DateTime 的存储方式 日期时间的显示方式

.NET 端

.NET 将 DateTime 存储为 number of Ticks since start of the Unix Epoch. 其他所有属性和字符串表示形式都是对该值的解释。

.NET 通过从 Windows 中提取用户文化设置来显示任何数值 - 包括 DateTime。这是一个非常有用的功能,因为这是我们通常不需要注意的一个重要部分。

Excel 端

旧的 Excel 格式使用十进制或浮点值。小数分隔符之前的部分是自 0-jan-1900 以来的 deys。它还有一个众所周知的错误,将 1900 年视为闰年。分隔符后面的部分表示一天中的时间。但它可能仍然有单独的日期和时间类型(这些类型已经失宠,因为在实践中几乎没有用处)。

如何显示这些值完全取决于您正在查看的 Excel 版本及其设置。

【讨论】:

感谢您的回答。所以,根据你的说法,我无法解决这个问题,因为它取决于 excel 版本? @AnuragRag 我 90% 确定它依赖于 Excel。可能有一种方法可以在存储期间在文件中注释所需的格式。但是我只有大约 50% 的把握,这些数据最终会存储在文件中,而不是客户端。 @AnuragRag:如果我找到的规范仍然正确:loc.gov/preservation/digital/formats/digformatspecs/… Excel 的“正常”格式以非常简写的方式存储,仅表示“内部格式编号”。并且只完全写出定义的格式。所以它应该能够提供文件的显示格式。但是,不知道如何做到这一点。我尽量避免使用 COM 互操作。 OpenOffice XML 好得多。 实际上是处理这些数据的下一步,在某些时候我需要与时间跨度进行一些比较,所以我想要 GridView 中的确切格式。让我们看看我是否能找出一些东西或一些东西else else 替代品。【参考方案2】:

我知道我回答这个问题迟了一年。我希望它可以帮助其他可能正在寻找类似解决方案的人。

excel中日期的默认格式是根据系统选择的语言来确定的。如果您需要默认 DD-MM-YYYY,则将语言更改为英语(印度)将解决它。

请注意:日期格式将根据打开文件的父系统而改变。因此,在您的 PC/笔记本电脑中,它可能会显示 DD-MM-YYYY,但是当我在我的系统中打开相同的文件时,它将是 MM-DD-YYYY,因为我的工作站中设置的语言是英语(美国)。

【讨论】:

【参考方案3】:

这是一个老问题;但是,我将这个答案留在这里,希望对某人有所帮助。

我遇到了和你一样的问题。在墨西哥,我们使用“日/月/年”日期格式。在 Excel 和其他信息系统中错误解释日期是一个非常常见的问题,其中“2020 年 3 月 6 日”(墨西哥记数法中的 6 月 3 日)在粘贴到 Excel 时被翻译为“2020 年 6 月 3 日”(3 月 6 日)或导出到旧系统。

我有一个将信息导出到 Excel 的 WPF C# 应用程序。同样的问题也发生在日期不明确的情况下(例如,16/10/2020 总是被正确解释为 10 月 16 日,因为它并不模糊)。我尝试了与您相同的解决方案,创建了一个预先格式化的字符串,然后将其导出。然而,结果是完全一样的。我认为 Excel 在内部应用与在单元格中键入内容时相同的过程,并且 Excel 会尝试找出它是哪种类型的信息(日期、数字、货币等)。因此,通过导出字符串,Excel 仍然尝试理解信息并确定它是日期,然后转换为日期单元格。

我还注意到 Interop 会忽略 Windows 和 Excel 区域设置。例如,如果我启动 Excel 并直接键入“2020 年 3 月 6 日”,则该信息会被正确解释为日期,并且是正确的日期(2020 年 6 月 3 日)。但是,通过使用 Interop,将“2020 年 3 月 6 日”写入 Excel 会显示为“2020 年 6 月 3 日”;将单元格格式更改为“长日期”显示“2020 年 3 月 6 日”(当然是西班牙语),因此这不仅仅是一个演示问题:日期实际上已更改。很明显,Excel 在为时已晚时才应用区域设置:在解释导出的日期之后。

我认为“正确”的解决方案是通过 Interop 命令配置工作簿的区域设置;但是,我发现了两个更快、更简单的解决方案。两者都有效。

第一个选项:强制 Excel 将日期作为文本字符串进行管理

这是快速而肮脏的解决方案。一个如此简单以至于看起来非常愚蠢的方法:只需在字符串的开头添加一个撇号(')。是的,我们在 Excel 中使用了很长时间的好方法。

DateTime my_date = DateTime.Today;
string my_string_date = my_date.ToString("dd/mm/yyyy");
string my_fixed_date = "'" + my_string_date;
excelsheet.Cells[1, 1] = my_fixed_date;

完成! Excel 将完全按照您的预期显示日期。但是,此方法有一个缺点:单元格包含文本字符串,而不是日期。更好的解决方案应该将单元格保留为日期;用户可能希望在公式中使用单元格的数据作为日期值。

第二个选项(我认为最好的解决方案):使用正确的日期格式格式化单元格

在这个解决方案中,实际的日期变量被导出。但在此之前,单元格会使用与我们希望显示日期的方式相匹配的日期格式进行格式化。在这种情况下,我们不需要预先格式化的字符串。

DateTime my_date = DateTime.Today;
excelsheet.Cells[1, 1].NumberFormat = “dd/mm/aaaa”;
excelsheet.Cells[1, 1] = my_date;

就是这样。在 Visual Studio 2019 中使用 WPF C# 进行了测试,这是可行的。

请注意,我使用的是西班牙日期格式(“dd/mm/aaaa”),因此您可能需要将其更改为您的 Excel 区域设置可以理解的字符串。这是该解决方案的缺点:它依赖于语言环境。 Excel 倾向于将公式和设置翻译成区域语言,这对于临时用户来说非常方便,但对于程序员来说却是一种痛苦。

另外请注意,我在插入值之前更改了单元格格式。我尝试在插入日期值后应用单元格格式,但没有成功。

第二种解决方案可以通过找到一种以独立于语言环境的方式定义单元格格式的方法来改进。如果我找到了怎么做,我会改变答案。

【讨论】:

以上是关于为啥将数据导出到 Excel 时日期格式会发生变化?的主要内容,如果未能解决你的问题,请参考以下文章

为啥java导出excel 日期格式不显示时分秒

django导出excel文件的内容为啥是空的

excel日期变数字为啥要点一下编辑栏才能变

使用 jasper 将日期导出到 Excel

excel的单元格为空 日期型 插入到SQL数据库 为啥会出现默认时间1900-1-2

导出到excel时s-s-rs不保持格式