.NumberFormat有时会返回错误的值和日期和时间

时间:2012-03-23 13:02:14

标签: excel excel-vba vba

似乎每个星期左右有人发布一个关于日期被转换(损坏?)到美国格式的问题。像许多其他人一样,我试图帮助但问题难以捉摸。我现在想知道我是否找到了原因。

我正在开发一个应用程序,我需要从Excel工作表中提取数据并将其输出为格式化的字符串,以匹配Excel用户可以看到的值。因此,如果格式为“1”的值显示为“1.00”,那么我希望字符串为“1.00”。

我通过将单元格值测试为数字,日期或时间来实现此效果。如果是,我检索数字格式并使用它来格式化单元格值:

With .Cells(Row, Column) 
  Output string = Format(.Value, .NumberFormat)
End With

在大多数情况下,这给了我正确的输出。但是,有时我会将美国日期和时间格式化为英国日期或时间。

经过Excel 2003和Excel 2007的大量实验,我发现了原因。 (我无法访问Excel 2010,但是从我推断的问题来看,它有同样的问题。)这个问题部分旨在向全世界揭示这个问题,因为我无法在互联网上发现任何其他人都注意到它。 (毫无疑问,有人会回复他们用谷歌搜索“xyz”并立即得到答案。)但是,这个问题的主要目的是寻求建议,以获得我在所有情况下所需的结果。

通常我输入日期,例如“23mar12”。 Excel将此识别为日期并将其格式化为“23-Mar-12”。我可以选择Format Cells并输入或选择自定义格式或选择其中一种日期格式,这样我就可以想到任何我想要的格式,包括日期和月份的非英文名称。

但是,在一种情况下,我选择的格式不是记录的格式:自定义格式“dd / mm / yyyy”记录为日期格式“* 14/03/2001”。在进一步下线之前,这显然不是问题。

我创建了一列日期和时间,并使用不同的自定义或标准格式对每个日期和时间进行格式化。我写了一个宏来为这些日期和时间中的每一个提取NumberFormat,并将其作为字符串写入相邻列。我还使用数字格式格式化了值,并将该字符串写入第三列。

在许多情况下,Excel选择和记录的格式不是NumberFormat返回的格式:

Excel format            NumberFormat
Date: * 14/03/2001       m/d/yyyy
Date: * 14 March 2001   [$-F800]dddd, mmmm dd, yyyy
Date: 14/03/2001        dd/mm/yyyy;@
Date: 14/03/01          dd/mm/yy;@
Date: 14/3/01           d/m/yy;@
Date: 14.3.01           d.m.yy;@
Date: 2001-03-14        yyyy-mm-dd;@
Date: 14 March 2001 (1) [$-809]dd mmmm yyyy;@
Date: 14 March 2001 (2) [$-809]d mmmm yyyy;@
Custom: hh:mm:ss        h:mm:ss
Time: * 13:30:55        [$-F400]h:mm:ss AM/PM
Time: 13:30:55 (1)      hh:mm:ss;@
Time: 13:30:55 (2)      h:mm:ss;@
Time: 01:30:55 PM       [$-409]hh:mm:ss AM/PM;@
Time: 1:30:55 PM        [$-409]h:mm:ss AM/PM;@

我添加了Excel格式列中的值(1)和(2),表示有两种明显相同的格式。从NumberFormat列中可以看出,在每种情况下,第二个版本都会抑制前导零。

大多数变化都没有重要影响。 “[$ -F800]”等显然是虚拟值而没有效果。显然,您可以将“F800”替换为Microsoft国家/地区代码,以将日期和月份的名称翻译为该国家/地区的语言。

但是,Microsoft标记为星号的三种标准格式无法接受。日期从小端到中端改变;时间从24小时变为12小时,并将星期几添加到“* 2001年3月14日”。

针对日期的星号,引用注释:“除了”类型“列表(”数字“选项卡,”单元格格式“对话框)中带有星号()的项目外,您应用的日期格式不会切换日期顺序使用操作系统。“星号与时间相关,引用注释:”除了“类型”列表(“数字”选项卡,“单元格格式”对话框)中带有星号()的项目外,您应用的时间格式不要用操作系统切换时间订单。“

如果必须,我可以警告我的用户标准日期和时间格式可能无法提供所需的结果。但是,如果他们想要流行的格式“dd / mm / yyyy”,他们就无法拥有它。例如,“dd-mm-yyyy”可以,但自定义格式“dd / mm / yyyy”变为日期格式“* 14/03/2001”变为“m / d / yyyy”。

回到我的开场白点:对于一个特定日期格式的奇怪处理是因为很多人声称他们的日期有时被转换为美式格式,这就是为什么这个问题难以理解?我在一组微软程序员的其他地方遇到过这种类型的问题,他不知道另一组正在做什么。这是为什么有些功能总是有效,有些则不然?一些Microsoft程序员知道在哪里寻找正确的格式而其他人不知道?

更重要的是,对我来说,任何人都可以建议:

  • 我如何获得真实的日期或时间格式?
  • 确定用户所选日期或时间显示格式的其他方法是什么?
顺便说一句:我记得大约三十年前我被告知美国军方不使用月/日/年格式;只有美国平民使用这种格式。谁能告诉我这是否属实?

BTW 2:类似的问题是Excel颜色。 Excel将其颜色保持为" ggbbrr"而其他人都认为他们是" rrggbb"。在使用它来控制屏幕之前,.Net Excel inter-op的程序员没有被告知并且没有反转Excel颜色编号。

3 个答案:

答案 0 :(得分:2)

打开使用不同区域设置保存的文本文件时,我主要遇到格式化和日期问题。处理这个问题的两个有用的单元属性是:

  • .Text返回显示的单元格值
  • .Value2返回未格式化的单元格值或日期序列号。

正如您所说,标准日期和数字格式取决于Windows区域设置,这可能不是所需的行为,因为同一工作簿可以在不同区域中以不同方式显示。 MS引入了数字格式的区域代码前缀(大约是Excel 2000?),如果需要,它会强制执行一致的显示,但需要明确选择它们。

如果您确实希望在用户输入日期或数字时查看日期或数字,则可以提取.xlsx文件的内容,查看工作表单元格格式和共享字符串xml定义,这些定义列出了已保存工作簿中的数字格式。我并不认为有必要这样做,因为底层值在内部存储为序列号,而且不会改变。

答案 1 :(得分:0)

顺便说一句:我在军队已经差不多30年了...... 我曾在直升飞机上工作,我被教导在飞机日志中使用这种格式:4月12日。所以,我仍然在写日期。这样,对于4/3/2012没有疑惑 - 是4月3日还是3月4日?

答案 2 :(得分:0)

我攻击了这个:我以已知格式重写原始数据。它依赖于DateSerial和TimeSerial:

'Google spreadsheet stores dates in USA format (MM/DD/YYYY).  We're in Australia, using DD/MM/YYYY, so we need to swap them.
                    '
                        With dc 'the cell who contains a date in USA format.
                             d = .Value      'capture value in USA format
                             t = TimeValue(d)
                             .NumberFormat = "dd/mm/yyyy" 'set to OZ format, so Excel knows the values were swapped in its internal math.
                             .Value = DateSerial(Year(d), Month(d), Day(d)) 'DateSerial takes y,d,m. We swap Month and Day components, to get OZ format dates
                             .Value = .Value + TimeSerial(Hour(t), Minute(t), Second(t))
                             dc.Font.Bold = True                         ' We bold the cells that are swapped, for debugging
                         End With
                    End If