三流君 ken3のmemo置き場

三流プログラマーのメモ書きです。主にVBAやWindowsの話題が多いです

挨拶・自己紹介:
失敗続きのAB型の変わり者 :三流プログラマー Ken3です
フリーのエンジニア・個人事業主です・・と書くと聞こえはイイが(それとなくカッコよく聞こえるが)、 現在は小さな案件の受注請負 と 短期派遣 で 日々つつましく?ほそぼそと暮らしてます。

よく検索されるキーワード: [質問回答XXXXさんへ] [CreateObject] [VBA] [JRA競馬オッズ]

ExcelからWord #データ差し込み 処理を #デバッグ してみた Excel VBA IsDate("1200-10") が True になるので小細工してみた・・・

f:id:ken3memo:20220220113844j:plain

IsDateで日付かチェック可能なのですが、
1200-12 みたいなYYYY-MMと取れる文字列を真 Trueと判断する
まぁ、当たり前のお話なのかなぁ・・・

なので、追加で、書式が文字列かチェックしてみたり、
置き換え前の文字に 日 が入っているか?チェックしてみたり、、、
いろいろ デバッグしてみました。

動画を見直すと自分の説明下手さにショックを受けつつ、
何かの参考となれば幸いです。

下記のteratailの質問
ExcelからWord #データ差し込み 処理を #デバッグ してみた
teratail.com
https://teratail.com/questions/ug68w33bvto3t0

いつもの あのあの そのその 酔っ払い解説動画は下記
www.youtube.com
https://www.youtube.com/watch?v=kd9C4CtZRJs

オープニング・質問内容 テスト実行
00:00 0.原因 日付チェックの関数 IsDate
04:40 1.対策1 書式設定で文字列 .NumberFormat でチェック
07:50 2.対策2 置き換え項目に 日 が入っていたら Like "*日*" 使用

0.原因 日付チェックの関数 IsDate
日付チェックの関数 IsDate で
1200-12 みたいなYYYY-MMと取れる文字列を真 Trueと判断する。
https://youtu.be/kd9C4CtZRJs?t=165
↑みたいな感じになると思います。

'日付か確認
If IsDate(ws.Range("A" & i).Offset(0, k).Value) Then '※1 IsDateだけで判断
.Replacement.Text = Format(ws.Range("A" & i).Offset(0, k).Value, "yyyy年m月d日")
End If

上記のように全てのデータに対して、
IsDateのチェックを行っているので、

? isdate("A123-12")
False
? isdate("1200-12")
True
? isdate("1200-13")
False

たまたま、1234-10 の ような文字列も日付だと判断してしまい、
Format関数で"yyyy年m月d日"に変換されるため。

対策1(修正案1) 動作は https://youtu.be/kd9C4CtZRJs?t=280 から見て下さい。
f:id:ken3memo:20220220114004j:plain
1.1 Excelの文字しか入らない列に書式設定で文字列と設定しておく
  列を指定後、書式設定で列全体を文字列にする
1.2 日付チェックの前に
.NumberFormat "@" など、文字列か先にチェックする

? range("E2").NumberFormat
@
など、.NumberFormatをチェック後、文字列以外をIsDateで日付チェックする

                '日付か確認
                If ws.Range("A" & i).Offset(0, k).NumberFormat <> "@" Then '文字列以外の時
                    If IsDate(ws.Range("A" & i).Offset(0, k).Value) Then  '※1 IsDateだけで判断
                        .Replacement.Text = Format(ws.Range("A" & i).Offset(0, k).Value, "yyyy年m月d日")
                    End If
                End If


対策2(修正案2) 動作動画は https://youtu.be/kd9C4CtZRJs?t=470 を見て笑ってください・・・

f:id:ken3memo:20220220114038j:plain
2.1 Word元ファイルの 置き換え文字 にルールを追加する
  項目名が XXXX日 と 日の文字が入っていたら(1行目の列見出し、置き換え元)
日付変換するように修正する
.Text = ws.Range("A1").Offset(0, k).Value '置換元、この文字を検索
↑この置き換えられる文字に 日 が入っていたら、変換するように細工する
If ws.Range("A1").Offset(0, k).Value Like "*日*" Then
など、Like演算子で、セットするデータが日付のルールかチェックするようにしてみては?

                '日付か確認
                If ws.Range("A1").Offset(0, k).Value Like "*日付*" Then '項目が日付の時
                    If IsDate(ws.Range("A" & i).Offset(0, k).Value) Then  '※1 IsDateだけで判断
                        .Replacement.Text = Format(ws.Range("A" & i).Offset(0, k).Value, "yyyy年m月d日")
                    End If
                End If


Excel側のコード

Option Explicit

' https://teratail.com/questions/ug68w33bvto3t0 の質問コードを修正

'プログラム開始
Sub Sashikomi_Insatsu()

    '変数設定
    Dim i As Long, k As Long
    Dim waitTime As Variant
    
    'シート設定
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets("差し込みデータ")
    
    'エクセルの最終行と最右列を取得
    Dim cmax As Long, cnt As Long
    cmax = Range("A65536").End(xlUp).Row
    cnt = Range("IV1").End(xlToLeft).Column
    
    'ワード起動
    Dim wdapp As Word.Application
    Set wdapp = CreateObject("Word.application")
    wdapp.Visible = True
    
    'テンプレートワードのパス取得
    Dim path As String
    path = ThisWorkbook.path & "\マクロ用.docx" 'エクセルのデータを1行ずつ処理
    
    For i = 2 To cmax
    
        'テンプレートワードを開く
        Dim wddoc As Word.Document
        Set wddoc = wdapp.Documents.Open(path)
        waitTime = Now + TimeValue("0:00:03")
        Application.Wait waitTime
        
        'テンプレートワードにエクセルデータを挿入
        'For k = 0 To cnt - 2  '改変、テストなので5固定にしてみた
        
        For k = 0 To 5  '←↑本番用に合わせて修正してください
        
            With wddoc.Content.Find
                .Text = ws.Range("A1").Offset(0, k).Value  '置換元、この文字を検索
                .Forward = True
                .Replacement.Text = ws.Range("A" & i).Offset(0, k).Value
                '日付か確認
                If ws.Range("A1").Offset(0, k).Value Like "*日*" Then '項目が*日*の時
                    If IsDate(ws.Range("A" & i).Offset(0, k).Value) Then  '※1 IsDateだけで判断
                        .Replacement.Text = Format(ws.Range("A" & i).Offset(0, k).Value, "yyyy年m月d日")
                    End If
                End If
                .Execute Replace:=wdReplaceAll  '置換実行
            End With
        Next k
        
        'ワードファイルを保存
        'On Error Resume Next '----------------------
        If ws.Range("A" & i).Value <> "" Then '-----
            Dim str As String
            str = ws.Range("A" & i).Value & ".docx"
            wddoc.SaveAs Filename:=ThisWorkbook.path & "\" & str
            
            'テンプレートワードを保存せずに閉じる
            wddoc.Close savechanges:=False
            
            'オブジェクト解放
            Set wddoc = Nothing
            
            'エクセルにデータを出力
            ws.Range("I" & i).Value = Now & "処理済"
        
        End If '------------------------------------
        On Error GoTo 0 '---------------------------
    
    Next i
    
    MsgBox "完了しました" 'プログラム16|プログラム終了

End Sub

Ken3 ホームページ 目次

分類:HPを大きく分けると4つの柱(分類)です。

  1. [VBA・マクロ プログラミング]の解説
    当店の人気はVBA系のCreateObject("XXXXXX.application")で他のアプリケーションを操作するサンプルが人気です
  2. [プログラマーの愚痴]では、あまり見せたくない三流プログラマーの内面かな。
    三流君を踏み台にする
  3. [古いクラシック ASP(Active Server Pages)]の解説。
  4. [元コンビニ店長時代の話]が弟に巻き込まれ、失敗した脱サラ、畑違い?の仕事で失敗。
主に上記4つの分類でHP作成やメルマガの発行を行ってます。
※更新頻度が落ちていて情報の鮮度が悪いです。



本当に三流なんです(笑):たまにスゴイですねなんて言われることもありますが、
真実は→ [三流君の真実は...] ←を初めに見てくださるとわかると思います。
(からくりは、成功例↑しか載せてなくて ヒドイ失敗例はお蔵入り迷宮入りが多かったりします)