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

Why Date format gets change while exporting data to Excel?

我正在处理 window 表格申请。在我的表单中,我有 GridView,其中有一列类型日期。日期列的日期格式为 dd-MM-YYYY.I,正在将此数据导出到 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 单元格类型不应为 problem.But 数据格式仍会转换。我在做什么错了?

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

  1. 如何存储日期时间
  2. 日期时间的显示方式

.NET端

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

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

Excel边

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

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

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

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

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

这是一个老问题;但是,我把这个答案留在这里,希望它能帮助到别人。

我遇到了与您完全相同的问题。在墨西哥,我们使用“day/month/year”日期格式。在 Excel 和其他信息系统中,错误解释日期是一个非常普遍的问题,其中“3/6/2020”(墨西哥表示法为 6 月 3 日)被翻译为“6/3/2020”(3 月 6 日)当粘贴到 Excel 或导出到遗留系统时。

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

我还注意到 Interop 忽略了 Windows 和 Excel 区域设置。例如,如果我开始 Excel 并直接键入“3/6/2020”,则该信息将被正确解释为日期,并且是正确的日期(2020 年 6 月 3 日)。但是,通过使用 Interop,将“3/6/2020”写入 Excel 显示为“6/3/2020”;将单元格格式更改为“长日期”显示“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 倾向于将公式和设置翻译成当地语言,这对普通用户来说非常方便,但对程序员来说却很痛苦。

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

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