ここから本文です

EXCEL VBA の文字列操作の達人様。

うどんさん

2017/12/2917:04:13

EXCEL VBA の文字列操作の達人様。

閲覧ありがとうございます。

私は長年使っている会社のツールのマクロを管理しています。しかし後付けであの機能もほしい、この機能もほしいとの要望に応えていた結果、気付いたらソースコードが数千行となりました。

原因の7割近くが文字列操作(判断)です。
例えば以下の文
●●●●: 2017/12/29 (01:00)

これらが以下の条件の体裁になっているかチェックする。
①●は定義文なのでチェックの必要はなし。
②Wコロンからチェックし、2017とWコロンの間に半角スペースがある必要があるかチェックする。

yyyy/mm/dd の体裁になっているかチェックする。
また、当日の日付になっているかチェックする。
29と01:00の間に半角スペースがある事をチェックする。
hh:mmの体裁になっているかチェックする。
時刻の両端に()があるかチェックする。

これらを全てチェックするソースを書くと、私はバカなのでめちゃくちゃ長くなってしまいます。

どうか達人様、これらの効率的なチェックの方法をご教示頂ければ大変幸甚で御座います。

閲覧数:
167
回答数:
5
お礼:
500枚

違反報告

ベストアンサーに選ばれた回答

30246kikuさん

2017/12/3108:31:44

以下でどうなりますか

何らかの返信はいただけるのでしょうか?

標準モジュールに以下を記述し、test を実行してみます
判別内容が足りなければ、追加してください

> 当日の日付になっているか
当日・・・わからなかったので、今日として以下で判別

   If (v(i) <> Format(Date, "yyyy/mm/dd")) Then

当日が今日でなければ、上記 Date 部分を変更して・・・・
日付は今日と比較してますが、時刻は 今より前 ・・・ チェックしてません

また、Samp1 の戻り値は文字列にしてましたが、
これもまた使いやすい様に変更してください


Option Explicit

Public Function Samp1(ByVal sSrc As String) As String
   Dim v As Variant
   Dim i As Long

   If (Not sSrc Like "*: ####/##/## (##:##)") Then
      Samp1 = "形式 NG"
      Exit Function
   End If

   v = Split(sSrc, " ")
   i = UBound(v) - 1
   If (v(i) <> Format(Date, "yyyy/mm/dd")) Then
      Samp1 = "日付 NG"
      Exit Function
   End If

   Samp1 = "時刻 NG"
   v = Split(Mid(v(i + 1), 2, 5), ":")
   Select Case v(0)
      Case "00" To "23"
         Select Case v(1)
            Case "00" To "59": Samp1 = "OK"
         End Select
   End Select
End Function


' 上記確認用

Sub test()
   Dim vC As Variant, v As Variant
   Dim s As String

   vC = Array( _
         Array("●●●●: {%1} (01:00)", 0), _
         Array("●●:●●: {%1} (01:00)", 0), _
         Array("●● ●●: {%1} (01:00)", 0), _
         Array("●● ●●:{%1} (01:00)", 0), _
         Array("●● ●●: {%1}(01:00)", 0), _
         Array("●●:●● {%1} (01:00)", 0), _
         Array("●●●●: {%1} (01:00)", -1), _
         Array("●●●●: {%1} (24:00)", 0), _
         Array("●●●●: {%1} (01:60)", 0), _
         Array("●●●●: {%1} (01:00", -1), _
         Array("●●●●: {%1} 01:00)", 0) _
      )

   For Each v In vC
      s = Format(Date + v(1), "yyyy/mm/dd")
      s = Replace(v(0), "{%1}", s)
      Debug.Print s; " → "; Samp1(s)
   Next
End Sub


ちなみに 2017/12/31 test 実行結果は

●●●●: 2017/12/31 (01:00) → OK
●●:●●: 2017/12/31 (01:00) → OK
●● ●●: 2017/12/31 (01:00) → OK
●● ●●:2017/12/31 (01:00) → 形式 NG
●● ●●: 2017/12/31(01:00) → 形式 NG
●●:●● 2017/12/31 (01:00) → 形式 NG
●●●●: 2017/12/30 (01:00) → 日付 NG
●●●●: 2017/12/31 (24:00) → 時刻 NG
●●●●: 2017/12/31 (01:60) → 時刻 NG
●●●●: 2017/12/30 (01:00 → 形式 NG
●●●●: 2017/12/31 01:00) → 形式 NG


※ Format 時の 分 は、m ではなく n を使われたらと・・・
m は、月 に良く使うので・・・
m で動かないわけではない・・・ですけど

この回答は投票によってベストアンサーに選ばれました!

ベストアンサー以外の回答

1〜4件/4件中

並び替え:回答日時の
新しい順
|古い順

tak********さん

2017/12/3107:36:06

クラスモジュールとか使ってますか?
擬似インターフェースとか使えるので、機能と実装を分けるとかするといいですよ

Prometheusさん

2017/12/2921:44:34

全く、スマートではありませんので、参考にならないかも知れませんが・・・

Sub Sample()
x = "●●●●: 2017/12/29 (01:00)"
c = InStr(x, ":")
If Mid(x, c + 1, 1) <> " " Then
MsgBox ("半角スペースなし!")
End If
If Mid(x, InStr(c, x, "2"), 10) <> CStr(Date) Then
MsgBox ("日付が違う!")
End If
If Mid(x, InStr(c, x, "(") - 1, 1) <> " " Then
MsgBox ("「(」の前に半角スペースがない!")
End If
t = Mid(x, InStr(c, x, "(") + 1, 5)
If t <> CStr(Format(t, "hh:mm")) Then
MsgBox ("時間のフォーマットが違う!")
End If
End Sub

簡単な説明です。

c = InStr(x, ":")

まず、「:」は、必ず存在するみたいなので、その位置を「c」に入れます。

これは、「●●●●」の中に「2」があると困るからです。

If Mid(x, c + 1, 1) <> " " Then

「:」のとなりが、「半角スペース」でなければ、

MsgBox ("半角スペースなし!")

メッセージ表示。

If Mid(x, InStr(c, x, "2"), 10) <> CStr(Date) Then

次に、「:」以降で、「2」を探します。

その、「:」以降で、初めて見つかった「2」から(「2」を含む)、「10」文字を取り出します。

その10文字と、本日の文字列としての(「CStr()」)日付(「Date」)が一致しなかったら、

MsgBox ("日付が違う!")

メッセージ表示。

If Mid(x, InStr(c, x, "(") - 1, 1) <> " " Then

今度は、「:」以降で、最初に見つかった「(」の左横の1文字が「半角スペース」でなければ、

MsgBox ("「(」の前に半角スペースがない!")

メッセージ表示。

t = Mid(x, InStr(c, x, "(") + 1, 5)

半角スペースの隣から、5文字抜き出して、「t」に入れています(「01:00」)。

If t <> CStr(Format(t, "hh:mm")) Then

その「t」が、文字列としてフォーマットした時間表記と一致しなければ、

MsgBox ("時間のフォーマットが違う!")

メッセージを表示しています。

もしかしたら、質問者とほとんど変わらないかも知れませんね。

それなら、申し訳ございません。

otu********さん

2017/12/2921:17:20

'やってみました。 今年2月29日なかったのですね? 関数が使えなくておどろいた。

Sub tesマクロ()
Dim v As Date
v = DateValue("2017/2/28")
Call マクロ1("●●●● : 2017/2/29 (01:00)", v)
End Sub
'-----------
Sub マクロ1(target As String, TDay As Date)
Dim reg, temp
Set reg = CreateObject("VBScript.RegExp")
With reg
.Global = True
.Pattern = "^.*: (\d{4}\/\d{2}\/\d{2}) \(\d{2}:\d{2}\)$"
If .Execute(target).Count > 0 Then
temp = .Replace(target, "$1")
If IsDate(temp) Then
If Int(TDay) = Int(CDate(temp)) Then
MsgBox "OK"
Else
MsgBox "日付が違います。"
End If
Else
MsgBox "正しい日付ではありません。"
End If
Else
MsgBox "形式にあやまりがあります。"
End If
End With
Set reg = Nothing
End Sub

msk********さん

2017/12/2920:07:33

チェックだけなら正規表現を利用すれば、こんな感じです。
因みにA1を文字列、時刻の妥当性は数字だけです。

With CreateObject("VBScript.RegExp")
.Pattern = ": " & Format(Date, "yyyy/mm/dd") & " \(\d\d:\d\d\)$"
If .test(Cells(1, "A")) = False Then MsgBox "チェックエラー"
End With

この質問につけられたタグ

みんなで作る知恵袋 悩みや疑問、なんでも気軽にきいちゃおう!

Q&Aをキーワードで検索:

Yahoo! JAPANは、回答に記載された内容の信ぴょう性、正確性を保証しておりません。
お客様自身の責任と判断で、ご利用ください。
本文はここまでです このページの先頭へ

「追加する」ボタンを押してください。

閉じる

※知恵コレクションに追加された質問は選択されたID/ニックネームのMy知恵袋で確認できます。

不適切な投稿でないことを報告しました。

閉じる