2024年12月14日土曜日

vbaツールはセキュリティソフトHP Sure Click Secure View環境では様々な意味不明なエラーが出る。

Gogle AIによると、

  • HP Sure Click Secure Viewは、HP Sure Click Secure Browsing拡張機能やHP Sure Click Secure Browserでファイルを開いた際に表示されるメッセージです。ファイルはマイクロVM(仮想マシン)に隔離されて編集可能なモードで起動するため、マルウェアやウィルスなどの脅威から保護されます。
だとすれば、vbaツールはおそらく、マルウェアやウィルスと解釈される。セキュリティソフトHP Sure Click Secure View環境では様々な意味不明なエラーが出る。解決策としては、HP Sure Click Secure Viewによる保護を解除すればよい。その方法はググれば良い。

2024年11月21日木曜日

vba ファイルのフルパスはApplication.GetOpenFilenameでゲットせよ

taka-skull

 vbaでファイルを扱うツールを作成する場合、入力となるファイルをmenuシートの特定セル(例えば、A10セル)にフルパスで書いてもらうといった作りになる。  ところが、フルパスのファイル名を指定することは、長々と文字列を書くことになり、意外と面倒くさい。そこで、A10セルの隣のセルに(ファイル)選択とか(フォルダ)参照とかいったボタンを作成し、サクッとGUI画面で設定できるようにしたい。
それを実現するため、ファイル選択ダイアログ(GUIだ)でファイルを選択し、そのファイルのフルパスを取得し、A10セルに設定するコードを書く。こんな感じで。  このコードを選択ボタン或いは参照ボタンにマクロ登録すれば、もう、完成だ。




Sub GetFileName()
Dim FileName as Variant
   FileName = Application.GetOpenFilename("Microsoft Excelブック,*.xlsx?")
   If FileName = False Then Exit Sub
   Range("A10").Value =  FileName 
End Sub
フォルダ選択ダイアログFileDialogとDir関数、ワイルドカード「*」を使う方法もある。

2024年11月15日金曜日

vbaでシートの特定の列だけコピーするは、不要な行は非表示にしてコピペすると良い。

vbaでシートの特定の列だけコピーするのは、全ての列を一旦、非表示にする。そして、必要な列だけを表示し、コピペする。と良い。とりわけ、ある条件でフィルターした結果だけをコピペする場合に具合がよろしい。

 Columns("A:Z").hidden = True  'A列からZ列を非表示にする
 Columns("A:D").hidden = False  ’A列からD列を表示する
 Range("A:Z").SpecialCells(xlCellTypeVisible).Copy Range("A1")

vbaで列の削除は一発でやれ

複数行の削除は、1行ずつやると、意図した行を消せないので、一発でやること。
 Columns("A:A,C:C,E:E,G:J").deleteで列削除は一発でやること。
 ちまちまと、Columns("A:A").Delete、次にColumns("C:C").Deleteとやると、意図した行が削除できない。

vbaで「インデックスが有効範囲にありません。」というエラーが出た時にはスペルミスを疑え

シート名やブック名に誤りがあると「インデックスが有効範囲にありません。」という謎のエラーが出る。ことがまま、ある。そういうとき、大体、スペルミスをしている。

vbaでシートをcopyすると、新ブックのシートにコピーされる、ActiveSheetはコピーされたシートになる。そして、新ブックをcloseすると、元のシートがアクティブになる。

アクティブシートは、スタックされている。新しいブックがcloseすれば、元のシートがアクティブになる。
 今、どのシートがアクティブなのかを把握していないと、プログラムは暴走し始める。

vbaをデバッグするときの作法について(how to debug for vba)

vbaのデバッグに便利なコマンド

  • イミディエイト・ウィンドウで、?ActiveSheet.Nameでアクティブシート名を出力する。
  • イミディエイト・ウィンドウで、?ActiveWorkBook.Nameでアクティブブック名を出力する。
  • イミディエイト・ウィンドウで、?Sheet("シート名").Range("A1").CurrentRegion.addressでセル範囲のアドレスを出力する。
  • ちょいちょいdebug.printせよ

2024年10月1日火曜日

SQL Serverのwhere句の%nnnnnnnn%と8桁の数字文字列を部分一致で抽出する際に9桁の文字列を除外する、ひとつの方法

 9桁目が数字以外のもの、[^0-9]とすればよい。
 例えば、where field名 like ’%12345678[^0-9]%' or field名 like ’%12345678'と書けば良い。
 これで、9桁以上の数字文字列が抽出されることはなくなる。
 ただし、9桁目に何らかの文字列(改行コード)でも可が必要だ。
でもないこともある。その場合は、お手上げだ。終わりを示す文字、例えば#を最後尾に付与するなどで、唯一無二、つまりユニークであることを保証する構造にする必要がある。
 いやいやそんなことないよ。where field名 like ’%12345678[^0-9]%' or field名 like ’%12345678'と書けば、9桁目に文字列がなくても良いと思う。

2024年7月22日月曜日

マイクロソフトからの「アクションが必要です」というメールになんとか対応してみた。

 マイクロソフトからのメールの本文によると、ワタシのoutlook.conへの接続方法は、「Microsoft の先進認証方法」になっていないため、2024 年 9 月 16 日以降はoutlookメールへ接続できなくなるというものだった。ちなみにワタシのソフト(macのメールapp)である。
 さて、どうしたらいいのか?
 メールには「ヘルプ記事「Modern Authentication Methods now needed to continue syncing Outlook Email in non-Microsoft email apps」を参照してください。」と記載されていた。誠に、不親切だ。
 このフレーズをぐぐると、macのメールappの場合、一旦、outlookのアカウントを削除し、再び、追加すれば(macのメールappは自動的にMicrosoft の先進認証方法になる)いいようだ。そして、やってみた。簡単にできた。
 これぐらいの話であれば、何故、メールの本文に書いてくれればいいのだがと、いつもながらの対応にイヤハヤ、感服してしまった。やれやれ、それそれ。

2024年4月27日土曜日

vbaのautoFilterで日付を指定してフィルターをかけるも思った通りにできない。なんでだろう?

 色々とグぐってみたら、どうやら、日付のフィルターには癖がある。というのは、例えば、2024/4/7と2024/04/27は別物になるようだ。
 これを回避するには、検索の対象列の書式に応じたフィルターをかけるということらしい。
 つまり、検索の列nの書式に応じて、AutoFilter n,Format(検索日,"yyyy/m/d")か、AutoFilter n,Format(検索日,"yyyy/mm/dd")にするを選択するわけだ。
 あるいは、AutoFilter n,Format(検索日,Cells(2,n).NumberForamatLocal)とする。

2024年3月23日土曜日

ドコモ光の回線でIP電話のオプションをやめたら、回線がリセットされて、復旧するまでとても大変だった話

ドコモ回線に自前のWiFiルータを付けインターネットに接続しているが、先日、ひかり電話(IP電話)のオプション契約を解約した。
 すると、NTTはその回線の設定を全て、リセットしたようだ。電話のオプションだけをナシにしてくれればいいのに、全部の登録情報をリセットしたようなので、利用者のワタシは、WiFi側からドコモ回線に接続のためのログインidやパスワードを再度、登録するといった初期設定をやり直すことになった。具体的にはブラウザのアドレスに192.168.2.1を打ち込んで、Wifiの管理画面に入り、勇気を持って、設定のボタンを押して、次々と出てくる画面に適当にかつ適切に答えるだけである。すると、なんとか、その回線は、ワタシのWifiからの接続を許可してくれたのだった。
 こう書くと、簡単な話に聴こえるかもですが、ここにたどり着くまでに、自分で色々と試行錯誤し、かつ、インターネットの接続業者のトラブル対応窓口に相談したりと、それはもう、大変な半日を過ごしたのでした。この初期設定のボタンのクリックは、相当の覚悟が必要だった。だって、これまで動いていたのだから。なんでこちらがリセットしなければならないんだと。やれやれ、それそれ。

2024年3月14日木曜日

excelのシートに関数を詰め込み過ぎて、再計算の砂時計に占領された。もはや、vbaを書くしかない。

 複数の列の値が一致したら、その行の特定の列を抽出するために、ユーザー定義の関数をvbaのfunctionで書いてみた。
 autofilterで複数の列をフィルターし、特定の列を取得するコードを書いてみた。まずは、debugで1行ずつ、動かして、OKだった。
 次にシートにその自作関数を埋め込むと、#VALUE!エラーとなった。どうも関数を埋め込んだシートとは異なるシートにautofilterでフィルターをかけるのが無理なようだ。
 そこで、AutoFilterでの自作関数は諦めて、index関数とsumproduct関数、row関数のみで作ってみた。例えば、こんな感じだ。
 =INDEX(Z:Z,SUMPRODUCT((X:X= Tn )*( Y:Y= Sn ), ROW(Z:Z)))
 X列の値がTnで、Y列の値がSnの行を見つけて、その行番号のZ列の値を抽出するという式である。
 埋め込みの箇所が少ないうちは、快調に動いてくれたのが、excelのシートに関数をたくさん埋め込むと、やたらと再計算で、砂時計がワタシのやりたいことを阻む。
 やむを得ず、関数で実現していた処理をvbaで書いた。まず、Autofilterを使わず、まず、X列の値がTn,Y列の値がSnの行を求め、Z列の値を取得するコードを書いた。そして、実行ボタンで必要な時に動かすようにした。この方式でも数が増えると、砂時計が出てきて、時間がかかるようだ。AutoFilterで複数の列をフィルターし、特定の列を取得するコードにすると、数が増えても砂時計は現れず、スーと終わった。AutoFilterは高速だな。シート内関数としては、呼べないけど。やれやれ。それそれ。

Function GetValue(Tn as long,Sn as Long) as String
  With thisworkbook.worksheets("SearchList")
    With .Range("A1")
      AotoFilter ColumnNoForX,Tn
      AutoFilter ColumnNoForY,Sn
      If WorksheetFunction.Subtotal(3,.Range("A:A")) > 1 then
        With .Range("A1").CurrentRegion.Offset(1,0) 
          For Each R in .Resize(.Rows.Count-1).SpecialCells(xlCellTypeVisible).Rows
            GetValue = R.Range("Z1").Value 
          Next R
        End With
      End If
    End With
  End With
End Function

2024年3月6日水曜日

excelでセルのn文字目が数字か否かを判定するとか、その類(たぐい)の話

 Anセルのn文字目を抽出するには Right(Left(An,n),1)だ。
 それが数字か否かは IsNumber(Value(Right(Left(An,n),1))))でいい。
 ちなみにValueを挟んでいるのがミソだ。
 これでセルのn文字目が数字か否かを判定することができる訳だが、いろんな付帯条件が付くことがある。例えば、3文字目が@の場合は除外するなら
 =IF(Left(An,3)="@",False,If(IsNumber(Value(Right(Left(An,n),1)))),True,False)
 そして、特定の文字Xが含まれるか否かは COUNTIF(An,"*X*")を使えばいい。

2024年1月30日火曜日

vbaでmenuシートを作成したときにパラメタのセルが指定されている(空白でない)かを判定する方法

vbaでmenuシートのセルA19にパラメタのセルが指定されていると仮定し、そのセルが空白でないか(指定されているか)を判定する方法は、こんな感じだ。

Sub parameterCheck()
Dim paramSpecified As integer
    paramSpecified = 0
    If WorkSheets("menu).Range("A10").Formula <>"" then paramSpecified = 1
End Sub

2024年1月7日日曜日

vbaでsqlを使う時の小さいけれども大事なこと。

 vbaでsqlを使う時の小さいけれども大事なこと。

  1. sqlのキーワードの前後、または片方に半角の空白を入れておく。
    • 例えば、SELECT*FROMMEMBERS;では、キーワードが認識できず、エラーとなる。SELECT * FROM MEMBERS;とするため、キーワードのSELECTの後やFROMの前後に半角の空白を意識して入れてあげるのだ。文字列の連結を繰り返していると、つい、忘れがちだ。意識して半角の空白を入れること、これが大事だ。
  2. sql文の記述にはダブルクウォート(")を使い、その中の文字列にはシングルクウォート(’)を使う。
  3. テーブルの内容といった結果、即ちrecordsetを返すsql(例えば SELECT)にはrs.open strSQLを使い、そうでなければ(例えばINSERT)cm.execute strSQLを使う。
'(1)
strSQL = ""
strSQL = strSQL & " SELECT "
strSQL = strSQL & "*" 
strSQL = strSQL & " FROM MEMBERS;"
'(2)
strSQL = ""
strSQL = strSQL + " INSERT "
strSQL = strSQL & " (NO,NAME) "
strSQL = strSQL & " VALUES(1,'田中');"