【问题标题】:Data not changing correctly in VBA, showing ####VBA 中的数据未正确更改,显示 ####
【发布时间】:2020-07-13 17:34:50
【问题描述】:

我从 JSON 数据集中以 (2017-04-03T15:36:45.000+0000) 的形式提取了一些日期,并将其转换为 (dd/mm/yy) 形式,这是我到目前为止的代码。

ActiveSheet.Cells(5) = Date
For i = 1 to Json("issues").Count
    Dim date_thing As String, date_part As String, finD As Date
    date_thing =  Json("issues")(i)("fields")("resolutiondate")

    date_part = Split (date_thing, "T")(0)
    finD = DateSerial(Split(date_part, "-")(0), Split(date_part, "-")(2), 
    Split(date_part, "-")(1))
    
    ActiveSheet.Cells(i+1, 5) = finD
    ActiveSheet.Cells(i+1, 5).NumberFormat = "dd/mm/yy" 
Next i

由于某种原因,其中两个日期的格式不正确,只是显示为“#######”。它们是 "2020-06-12T23:44:00.000+0000""2020-04-10T21:37:31.000+0000"。有什么问题?

【问题讨论】:

  • 您的本地默认数据格式是什么?更正显示的日期中间的数字是否比最后一个大?
  • 请尝试我在回答中建议的想法,以免让 Excel 猜测哪个是日哪个月...

标签: json excel vba jira-rest-api


【解决方案1】:

仅处理字符串,当您尝试格式化时,Excel 只会猜测哪个是日期和月份...我认为,您必须告诉他每个是哪个。请尝试下一种方法:

Dim d As String, date_part As String, finD As Date
   d = "2020-06-12T23:44:00.000+0000" 'only for testing reason. You use Json...
   date_part = Split(d, "T")(0)
   finD = DateSerial(Split(date_part, "-")(0), Split(date_part, "-")(2), Split(date_part, "-")(1))
   Debug.Print Format(finD, "dd/mm/yy")
   ActiveSheet.Cells(i+1, 5).value = finD
   ActiveSheet.Cells(i+1, 5).NumberFormat = "dd/mm/yy"

我不明白您的月份和日期。如果它不会返回您需要的内容,只需将中间项与最后一项切换...

这样,Excel 就再也不用猜了。当您“指示”它时,它将始终将第二个术语视为月/日。

【讨论】:

  • 如何打印“Debug.Print Format(finD, "dd/mm/yy")”,因为现在我只是通过“ActiveSheet.Cells(i +1, 5) = findD
  • 虽然它当然可以工作,但我认为您不应该重复 Split-command 3 次 - 而是使用中间变量。使其更易于阅读。
  • @ben101:除非您真的需要 Excel 中的字符串,否则您应该将 DateSerial 的结果写入 Excel。这样,值将存储为Date,而不是看起来像日期的String。您可以设置单元格的数字格式以匹配您想要的显示方式。
  • @FaneDuru:不,它是一个字符串。 Format 的结果是一个字符串,该字符串被写入单元格。根据语言设置和 Excel 版本,它可能被视为日期。总是写一个日期作为日期并应用格式,否则下一个关于 SO 的问题并不遥远。
  • 现在还是不行 我还有其他错误的,包括 "2017-11-30T11:29:46.000+0000", "2020-05-22T23:22:05.000+ 0000”和“2020-05-28T21:13:01.000+0000”
【解决方案2】:

不想窃取 FaneDurus 的答案,但评论太多了。

因此,您的任务是将String 转换为DateDate 在内部存储为数字(双精度),您有很多可能以您喜欢的任何方式对其进行格式化、计算等等。

所以你得到的String 类似于"2020-05-28T21:13:01.000+0000"。请务必记住,从技术上讲,这是String,而不是Date。 Excel 擅长从字符串中猜测日期,但它无法创造奇迹,所以为了确保您处于保存状态,请使用 String functions 自己拆分字符串。

有很多方法可以做到这一点,但我认为最简单的方法是使用Split-command(就像 FaneDuru 所做的那样)。第一步是将 DateTime 部分分开,您已经这样做了:

dateTimeParts = Split(date_thing, "T")

现在我们有一个包含 2 个元素的数组,第一个 (index=0) 有 "2020-05-28",第二个 (index=1) 有 "21:13:01.000+0000"。下一步是将日期部分拆分为年、月和日。它们用破折号隔开,所以我们使用

Dim dateParts() as string
dateParts = split(dateTimeParts(0), "-")

现在dateParts 中有 3 个字符串,一个代表年份,一个代表月份,一个代表日期。下一个任务是从这 3 个部分创建一个真正的 Date,VBA 为此提供了 DateSerial 函数:它从 3 个数字创建一个日期。您可以使用 dateParts 中的三个字符串来提供它,但这些字符串仍然是字符串。 VBA 会尝试转换它们,但最好在代码中写下来 - 隐式转换是许多错误的根源。为了更好的可读性,我使用了三个中间变量,这是一个口味问题,但我不喜欢将许多操作放在一行中。 CLng 会将String 转换为Long

Dim day as long, month as long, year as long, finalDate as Date
year = CLng(dateParts(0))
month = CLng(dateParts(1))
day = CLng(dateParts(2))
finalDate = dateSerial(year, month, day)

现在您想将日期写入单元格,它应该以“DD/MM/YY”的形式显示。不要将宝贵的Date 转换回字符串(就像Format 函数一样)。相反,将日期值写入单元格并格式化单元格,以便日期以您想要的方式显示。我假设ActiveCell,将其调整为您需要的任何单元格,但请不要使用Select 设置ActiveCell

Activecell.Value = finalDate
Activecell.NumberFormat = "dd/mm/yy"

这样,您以后可以毫无问题地更改单元格的格式(例如使用 4 位日期),或者将格式更改为写入日期或月份的名称。这只会改变日期的显示方式 - 日期值本身保持不变。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-03
    相关资源
    最近更新 更多