我有一个日期列,其中包含混合格式的日期。例如:
一个
1990年3月21日
1990年3月21日
因此,基本上一列中有两种不同的格式:dd.mm.yyyy
和mm/dd/yyyy
。我正在尝试编写VBA脚本以将列中所有日期的格式更改为yyyy-mm-dd
。这就是我到目前为止所做的:
Sub changeFormat()
Dim rLastCell As Range
Dim cell As Range, i As Long
Dim LValue As String
i = 1
With ActiveWorkbook.Worksheets("Sheet1")
Set rLastCell = .Range("A65536").End(xlUp)
On Error Resume Next
For Each cell In .Range("A1:A" & rLastCell.Row)
LValue = Format(cell.Value, "yyyy-mm-dd")
.Range("B" & i).Value = LValue
i = i + 1
Next cell
On Error GoTo 0
End With
End Sub
我知道这不是优雅的代码,但我是VBA的初学者所以请原谅我。
该代码的问题在于它只是将未更改的A列重写为B列,当我将格式函数中的参数从yyyy-mm-dd
更改为dd/mm/yyyy
时,它可以正常工作,但仅适用于格式为mm/dd/yyyy
的日期,并且dd.mm.yyyy
叶未被触及。我很感激任何建议。
答案 0 :(得分:8)
更新:新答案
这是一个可以完成这项工作的解决方案!子例程包括一个替换函数(函数本身非常有用!)。运行sub,A列中的所有出现都将被修复。
Sub FixDates()
Dim cell As range
Dim lastRow As Long
lastRow = range("A" & Rows.count).End(xlUp).Row
For Each cell In range("A1:A" & lastRow)
If InStr(cell.Value, ".") <> 0 Then
cell.Value = RegexReplace(cell.Value, _
"(\d{2})\.(\d{2})\.(\d{4})", "$3-$2-$1")
End If
If InStr(cell.Value, "/") <> 0 Then
cell.Value = RegexReplace(cell.Value, _
"(\d{2})/(\d{2})/(\d{4})", "$3-$1-$2")
End If
cell.NumberFormat = "yyyy-mm-d;@"
Next
End Sub
将此功能放在同一个模块中:
Function RegexReplace(ByVal text As String, _
ByVal replace_what As String, _
ByVal replace_with As String) As String
Dim RE As Object
Set RE = CreateObject("vbscript.regexp")
RE.pattern = replace_what
RE.Global = True
RegexReplace = RE.Replace(text, replace_with)
End Function
工作原理:我有一个漂亮的RegexReplace函数,允许你使用正则表达式替换。 sub mearly循环通过你的A列,并为你提到的那两个案例做一个正则表达式替换。我首先使用Instr()的原因是为了阻止它是否需要替换,以及哪种类型。从技术上讲,你可以跳过这个但是对不需要它的单元进行替换是非常昂贵的。最后,我将单元格格式化为您的自定义日期格式,无论内部是什么安全措施。
如果你不熟悉Regex(对于ref:http://www.regular-expressions.info/),我使用的表达式是:
答案 1 :(得分:4)
你真的不需要VBA。这个单行工作表公式将起到作用:
=IF(ISERROR(FIND(".",A1)),IF(ISERROR(FIND("/",A1)),"invalid format",
DATE(RIGHT(A1,4),LEFT(A1,2),MID(A1,4,2))),
DATE(RIGHT(A1,4),MID(A1,4,2),LEFT(A1,2)))
这假设日期和月份总是以两位数字给出(例如总是03而不是3),年份有四位数(即“限制”到1000-9999年)。但如果您不是这种情况,那么可以很容易地调整公式以适合您的目的。
答案 2 :(得分:3)
看看这是否符合您的要求。您可能需要根据自己的应用进行一些定制。
希望这有帮助!
Sub convertDates()
Dim rRng As Range
Dim rCell As Range
Dim sDest As String
Dim sYear, sMonth, sDay, aDate
'Range where the dates are stored, excluding header
Set rRng = Sheet1.Range("A2:A11")
'Column name of destination
sDest = "B"
'You could also use the following, and just select the range.
'Set rRng = Application.selection
For Each rCell In rRng.Cells
sYear = 99999
If InStr(rCell.Value, ".") > 0 Then
aDate = Split(rCell.Value, ".")
If UBound(aDate) = 2 Then
sDay = aDate(0)
sMonth = aDate(1)
sYear = aDate(2)
End If
ElseIf InStr(rCell.Value, "/") > 0 Then
aDate = Split(rCell.Value, "/")
If UBound(aDate) = 2 Then
sDay = aDate(1)
sMonth = aDate(0)
sYear = aDate(2)
End If
End If
With rCell.Range(sDest & "1")
If sYear <> 99999 Then
On Error Resume Next
.Value = "'" & Format(CDate(sMonth & "/" & sDay & "/" & sYear), "YYYY-MM-DD")
'If it can't convert the date, just put the original value in the dest
'cell. You can tailor this to your own preference.
If Err.Number <> 0 Then .Value = rCell.Value
On Error GoTo 0
Else
.Value = rCell.Value
End If
End With
Next
End Sub
答案 3 :(得分:1)
@ Jean-FrançoisCorbett有一个有效的公式解决方案,但可以通过上述错误消息(基于#VALUE!
提供信息)和另一个IF,两个DATE,应用可缩短一半以上IFERROR而非ISERROR,SUBSTITUTE代替LEFT,MID,RIGHT集合:
=IFERROR(1*(MID(A1,4,3)&LEFT(A1,3)&RIGHT(A1,4)),1*SUBSTITUTE(A1,".","/"))
这适用于@Issun在对OP的注释中提到的解释,并假设输出将是格式为yyyy-mm-dd
的单元格。
可以用如下子程序编写:
Sub Macro1()
Range("B1:B10").Formula = "=IFERROR(1*(MID(A1,4,3)&LEFT(A1,3)&RIGHT(A1,4)),1*SUBSTITUTE(A1,""."",""/""))"
End Sub
答案 4 :(得分:0)
以下是一个简单的解决方案:
Sub ChangeFormat1()
Dim ws as Worksheet
Set ws = Thisworkbook.Sheets("Sheet1")
LR = ws.cells(rows.count,1).End(Xlup).Row
with ws
For I = 1 to LR
.cells(I,2).value = .cells(I,1).value
Next
End with
ws.range("B1:B" & LR).numberformat = "yyyy-mm-dd"
End Sub
答案 5 :(得分:-1)
月(日期)&amp; “ - ”&amp;日(日期)&amp; “ - ”&amp;年份(日期)