Excel中的SQL Server Datetime对象持续重新格式化问题
Posted
技术标签:
【中文标题】Excel中的SQL Server Datetime对象持续重新格式化问题【英文标题】:SQL Server Datetime object persistent reformatting issue in Excel 【发布时间】:2017-01-20 10:41:48 【问题描述】:我在使用 Excel 2013 中的 SQL Server DATETIME
对象时遇到了一个烦人的问题。该问题已在 SO 中多次说明,我知道解决方法是重新格式化 Excel 中的 DATETIME
对象这样做:
yyyy-mm-dd hh:mm:ss.000
这很好用,但我讨厌每次都这样做。除了创建宏之外,是否有永久性的解决方法?我需要保持DATETIME
对象的粒度,所以我不能使用SMALLDATETIME
。我目前在 win7 机器上使用 Microsoft SQL Server Management Studio 2008 r2。
提前致谢。
-Stelio K.
【问题讨论】:
您是如何将其导入 Excel 的?因为这也可以通过宏来完成,将所有步骤缩小到单击按钮。还有数据源链接进入表格,您可以对其进行格式化。 您似乎无法在没有其他麻烦的情况下修改 Excel 的默认粘贴行为。虽然很烦人,但我认为这是你阻力最小的道路。 保存特殊电子表格是一步,转换为日期时间是一步。如果它们都是临时查询,那么日期时间列的位置是可变的,所以请告诉我您的解决方案如何解决问题。 如果您考虑一下这些词的含义,就会出现“默认粘贴行为”。这是 Excel 在粘贴时默认执行的操作。在我看来,您的意见没有建设性。 @StelioK 您(或最终用户)可以在任何版本的 Excel 2013 中使用 Power Query 来执行您想要的任何类型的操作,包括应用类型和格式。无需使用代码。 【参考方案1】:没有任何代码,很难猜出如何数据从 SQL Server 到 Excel。我认为这不是通过数据连接,因为 Excel 直接将数据显示为日期不会有任何问题。
数据连接呢?
Excel 在处理数据连接时不支持任何类型的格式或任何有用的设计器仅。该功能由 Power Query 或数据透视表设计器提供。 Power Query 已集成在 Excel 2016 中,可用于 Excel 2010+ 的下载。
为什么需要格式化日期
Excel 不保留类型信息。一切都是字符串或数字,其显示由单元格的格式决定。
日期使用 OLE 自动化格式存储为小数 - 整数部分是自 1900-01-01 以来的日期数,小数部分是时间。这就是System.DateTime
具有FromOADate
和ToOADate
功能的原因。
要创建带有日期的 Excel 工作表,您应该在生成单元格的同时设置单元格格式。
如何格式化单元格
如果您使用 Open XML SDK 或 EPPlus 之类的库,则相对而言这样做。以下示例根据客户列表创建 Excel 工作表:
static void Main(string[] args)
var customers = new[]
new Customer("A",DateTime.Now),
new Customer("B",DateTime.Today.AddDays(-1))
;
File.Delete("customers.xlsx");
var newFile = new FileInfo(@"customers.xlsx");
using (ExcelPackage pck = new ExcelPackage(newFile))
var ws = pck.Workbook.Worksheets.Add("Content");
// This format string *is* affected by the user locale!
// and so is "mm-dd-yy"!
ws.Column(2).Style.Numberformat.Format = "m/d/yy h:mm";
//That's all it needs to load the data
ws.Cells.LoadFromCollection(customers,true);
pck.Save();
代码使用 LoadFromCollection 方法直接加载客户列表,无需处理单元格。 true
表示生成了一个header。
有等效的方法可以从其他来源加载数据:LoadFromDatatable、LoadFromDataReader、CSV 数据的 LoadFromText,甚至是锯齿状对象数组的 LoadFromArrays。
奇怪的是,指定m/d/yy h:mm
或mm-dd-yy
格式使用用户的语言环境进行格式化,不是美国格式!这是因为这些格式内置在 Excel 中,并被视为与区域设置相关的格式。在日期格式列表中,它们以星号显示,表示它们受用户区域设置的影响。
这种奇怪的原因是,当 Excel 10 年前迁移到基于 XML 的 XLSX 格式时,出于向后兼容的原因,它保留了旧 XLS 格式的怪癖。
当 EPPlus 保存 xlsx
文件时,它会检测到它们并存储对内置格式 ID(分别为 22 和 14)的引用,而不是存储整个格式字符串。
查找格式 ID
标准格式 ID 列表显示在 Open XML 标准的NumberingFormat element documentation page 中。 Excel 最初定义的 ID 为 0(常规)到 49。
EPPlus 不允许直接设置 ID。它检查格式字符串并仅映射格式 0-49,如 ExcelNumberFormat 的 GetBfromBuildIdFromFormat 方法中所示。为了获得 ID 22,我们需要将 Format 属性设置为 "m/d/yy h:mm"
另一个技巧是检查现有工作表的样式表。 xlsx
是一个 XML 文件的压缩包,可以使用任何解压缩工具打开。样式存储在xl\styles.xml
文件中。
【讨论】:
我在我的 OP 中声明数据只是简单的复制和粘贴。 @StelioK 您可以考虑将其作为编辑而不是 cmets 放入您的帖子中,特别是在运行查询后从 SSMS“结果”窗格中复制。我认为我最初的假设是正确的,但是对于您可能从事的工作,有无数的选择有一些开放的解释。 @StelioK 您可以根据需要使用“导出数据”向导直接生成 Excel 文件并避免格式猜测。实际上,您只是在复制文本。 Excel 会识别某些格式,但不会根据猜测更改样式。以上是关于Excel中的SQL Server Datetime对象持续重新格式化问题的主要内容,如果未能解决你的问题,请参考以下文章
从 excel 导入数据时防止 SQL Server 2008 中的行重复
如何将sql server中的大量数据导出到excel文件中
SQL Server、Excel 和 MS Access 中的日期差异