生成的 Excel 文件在不同系统中显示不同的日期值(Asp.net Web 应用程序)

Posted

技术标签:

【中文标题】生成的 Excel 文件在不同系统中显示不同的日期值(Asp.net Web 应用程序)【英文标题】:Generated Excel file showing date value differently in different systems ( Asp.net web application) 【发布时间】:2019-09-28 23:07:51 【问题描述】:

我有 asp.net 网络应用程序,它向带有 .xls 附件的用户发送电子邮件,这个文件有几个显示日期的列,所以当用户在这些系统中下载这个 excel 文件时,只有系统设置在dd-mm-yyyy 格式的日期显示正确,对于系统设置不是 dd-mm-yyyy 格式的所有其他用户,日期列显示不正确。

知道如何解决此问题,要求是使日期列以 dd-mm-yyyy 格式显示,而与用户时间设置无关

我正在使用以下代码行通过电子邮件发送 .xls 文件

 using (StreamReader stRDR = new StreamReader(Server.MapPath("~/2.1.3.2-B-MAILER.html")))
                
                    sHTMLbody = stRDR.ReadToEnd();
                    sHTMLbody = sHTMLbody.Replace("NAME", sSalesL2name.ToString());
                    sHTMLbody = sHTMLbody.Replace("MESSAGEBODY", sMsgBodyTemplate);
                
                var dtServer = DateTime.Now;
                string FileName = "SalesL2_" + sSalesL2sapcode + ".xls";
                String sPath = Path.GetTempPath() + FileName;
                //String sPath = Path.GetTempPath() + sL3sapcode.ToString() + dtServer.ToString("_yyyy-MM-dd__HH-mm-ss") + ".xls";
                FileInfo FI = new FileInfo(sPath);
                StringWriter stringWriter = new StringWriter();
                HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWriter);
                // For the below line to work, we need [override void VerifyRenderingInServerForm as part of class]
                GridView gvTemp = new GridView();
                gvTemp.AllowPaging = false;
                gvTemp.DataSource = dtResult;
                gvTemp.DataBind();
                gvTemp.RenderControl(htmlWrite);
                gvTemp = null;
                System.IO.StreamWriter vw = new System.IO.StreamWriter(sPath, true);
                stringWriter.ToString().Normalize();
                vw.Write(stringWriter.ToString());
                vw.Flush();
                vw.Close();
                Attachment attXLS = new Attachment(FI.FullName);
                //"application/vnd.ms-excel";
                // Send Email
                // Create new Mail Object
                objMail = new MailMessage(); // Create new Mail Object
                objMail.From = new MailAddress("ersdocumenttracking@hcl.com");

**Stored proc**
select distinct t1.[Project code],t1.[Project Description],t1.[Start Date],
t1.[End Date],t1.[Customer],t1.[Customer Name],t1.[Customer Group],
[AM Sales SAPID],[AM Sales Name],[L3 Sales SAPID],[L3 Sales Name],[L2 sales SAPID],[L2 sales Name],
t1.[Proj Category Description],t1.[DU Desc (L4)],t1.[SDU Name (L3)],
t1.[PM Code],t1.[PM Name],t1.[VBDU Desc (L2)],t1.[SPM Code],t1.[SPM Name],t1.[DUH Code],t1.[DUH Name],
t1.[SDUH Code],t1.[SDUH Name],[VBDUH Code],[VBDUH Name],[Geo Reg Name],[Customer SOW],t1.[MSA],
[MSA Start Date],[MSA End Date],[SOW Start Date],[SOW End Date],[Document applicability],
[Avg Rev based on AMJ '18 PP (in $K)] [Avg Rev based on last quarter PP (in $K)],[UAR $K],
[MSA RAG check],[SOW RAG check],
[PONumber],[POValidFrom],[POValidTo],[Balance in $K],
[PO RAG check],[PO Insufficient flag],[MSA Documents remarks], [SOW Documents remarks],
[PO Documents remarks] 
from [tbl_MSA_SOW] as t1 left join [tbl_PO] as t2 
on t1.[Project code] = t2.[Project Code]
inner join [tbl_Sales_mapping] as t3 
on t1.[Project code]=t3.[Project code] 
where (t1.[MSA RAG check]=@RagValue or t1.[SOW RAG check]=@RagValue
or t2.[PO RAG check]=@RagValue) 
and t3.[L2 sales SAPID]=@sapid and t3.[AM Sales Name] !='-'

【问题讨论】:

开始使用专门的库来创建 Excel 文件,例如 EPPlus。您现在所做的只是创建一个扩展名为 .xls 的 HTML 页面。 【参考方案1】:

你不应该这样做。如果您要发送 Excel 表格,则应向用户显示日期。让excel根据用户的系统设置显示日期。不要预设格式。如果您这样做,那么用户将日期作为字符串获取,并且必须对其进行转换才能对数据执行任何有用的操作。 还有一点,有什么理由,为什么要发送 xls 而不是 xlsx?鉴于这是通过电子邮件进行的,用户会更乐意下载 xlsx 文件,因为它们保证不包含宏。 Xls 被认为更危险,许多电子邮件客户端阻止用户打开 xls,正是出于这个原因。

编辑

看了你的代码,我更清楚地理解了这个问题。您制作的不是真正的 Excel 电子表格;它只是一个添加了 .xls 扩展名的文本文件。

要了解区别,请创建一个新的 Excel 电子表格,输入一些示例数据,然后将其保存为 xls(Excel 97 格式)。现在在记事本中打开文件,看看你得到了什么。现在打开您通过代码生成的文件。

这里发生了什么? Excel 足够聪明地认识到,虽然您生成的文件具有错误的扩展名(即文件的内容不是 xls 所需的内容),但它具有可以在电子表格中显示的数据,因此可以方便地加载它。

将扩展名更改为 xlsx 没有帮助。

您有两个选择:1) 诚实并使用适合您生成文件格式的扩展名(*.txt、*.csv 等)或 2) 您需要将 Excel 工作簿生成为本机 Excel 文件。

如果您选择后一种方式,则有多种选择:1) 使用 Office 互操作性库,2) 使用第三方 Excel 库(其中一些是免费的 - 请使用 Google c# Excel 库)或 3) 生成您自己的库。我个人不得不选择 3),因为 1) 的问题是 Office 需要安装在 Web 服务器上,而 2) 它要么花钱,要么意味着使用免费软件,我的雇主通常不乐意这样做。

如果你想做 3) 我可以给你一些帮助。我推荐的第一步是在 Excel 中创建一个示例 xlsx 文件并保存。然后将资源管理器中的扩展名更改为 .zip(是的!!)并解压缩。然后检查内容。你会发现它很有趣,但那是你需要创造的。这并不容易,但可以使用 .Net 中的内置函数来完成。

编辑 2)

如果您选择走 csv 路线(我不确定您这里的内容是否真的是 csv,您需要打开生成的文件才能确定),那么它目前仅适用于具有 dd 的系统-mm-yyyy 日期格式。要使其适用于任何语言环境,您需要采用 ISO 8601 格式的日期(即 yyyy-mm-dd)。为此,您有两个选择。首先,在生成数据时更改您的存储过程以格式化日期,因此:

SELECT CONVERT(varchar(10), your_date, 126) AS your_date FROM your_table;

(请注意,您应该为输出列提供别名,否则它会得到 Expr1 等)。 其次,您可以在检索数据后将 DataColumn 添加到 DataTable 中,逐步检查 DataTable 的行并将新列分配为预先存在的日期列的 ISO 8601 格式版本,然后删除预先存在的日期列。在生成文本输出之前执行所有这些操作。

【讨论】:

ok 乔纳森明白了你的意思,你的意思是说,根据用户系统设置,日期列会出现,是的,如果它显示正确,那很好,但在我们的例子中,用户不是dd-mm-yyyy 它没有正确显示我的意思是日期列,正如你所说的不显示格式,所以我需要在代码中删除什么你能帮我吗 您没有显示任何创建电子表格的代码,只有创建文件名的代码。也请考虑我关于 xlsx 的观点。 SO 不是免费的编码网站。我们在这里为您提供帮助,但不是为您编写代码。请查看提问指南。 是的,乔纳森,谢谢,我明白,excel 文件中的数据是从存储过程生成的,该存储过程具有列开始日期和结束日期,并且用于这些列的数据类型是日期时间。 好的,乔纳森感谢您对上述问题的详细分析,我会对其进行调查,如果需要任何帮助,我会通知您,再次感谢您的宝贵时间。 嗨乔纳森,这里有个疑问,所以如果我在代码中将扩展名更改为 .csv,无论系统中的时间格式如何,datetime 列都会在任何系统中正确显示日期。

以上是关于生成的 Excel 文件在不同系统中显示不同的日期值(Asp.net Web 应用程序)的主要内容,如果未能解决你的问题,请参考以下文章

Excel 和 OpenOffice 中的日期格式不同

VBA 在 Excel 2016 中以不同方式处理日期?有这方面的文件吗?

网页抓取不同日期的excel文件

excel日期格式与vba中的不同

在excel的VBA里如何获取日期和星期几

jasperreport+iReport 生成的Excel全在一个单元格内