ExcelVBA覚書 リモート実行

リモート実行にはいろいろやり方があるようだが、レジストリを触らなきゃいけないとかいわれると気が引けるものだ。

で、行き着いたのは、CreateObject(“WbemScripting.SWbemLocator”)を利用するこのスクリプト。

[VBScript] 他端末のプログラムをリモートで実行する

これを参照してリモートサーバのバッチファイルを叩くことに成功。

ありがとう!

ExcelVBA覚書 Clipboardに格納

クリップボードに値を設定するときは、「DataObject」を使うらしいが、CreateObjectで利用するときはいかのようにするらしい。

Dim buf As String

buf = "あいうえお"
With CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
    .SetText buf
    .PutInClipboard
End With 

VBA覚書 グループ開閉(行)

マクロの記録中だと、
メニュー「データ」→「グループとアウトラインの設定」→「詳細データの表示」
と、メニュー上で行うと記録できるらしい。

Excel質問掲示板(VBA) シートの外のグループ化の展開はできますか?

ということで、開くとき
ExecuteExcel4Macro “SHOW.DETAIL(1,” & CStr(グループの開始行) & “,True)”

閉じるとき
ExecuteExcel4Macro “SHOW.DETAIL(1,” & CStr(グループの開始行) & “,False)”

VBA覚書 保存させずに終了させる方法

保存ボタンを押されたときに保存させないのは、WorkbookのBeforeSaveで「Cancel = True」の1文を入れたらよい。
では、終了時に保存確認させたくないときはどうするか。
保存したことにして確認ダイアログを出さないようにする手があるようだ。


Private Sub Workbook_BeforeClose(Cancel As Boolean)
    If MsgBoxInfomation("終了確認", "終了してよろしいですか?", vbQuestion) <> vbYes Then
        Cancel = True
    End If
    ThisWorkbook.Saved = True  '保存した!ということにする
End Sub

Webアプリ覚書 HTML5・CSS3・IE対応

Bootstrap3関連

自分はBootstrap2のときに初めて使ったのだけど結構奥深いので、公式ページではよくわからない箇所はリンクを参照。
Bootstrap3移行ガイド
Bootstrap3 徹底解説!

ファビコンを作る

結局一番使いやすいのはX-Icon Editorだった。(ただし、64、32、24、16ビットサイズにしか対応していない。)
他のは使い勝手がものすごく悪かったり、pngに対応してなかったり、下手をするとウィルス付だったり・・・

X-Icon Editor

より見やすい画面に(コントラスト比の算出)

こういうのはWebアプリだけでなく、いろいろ使えそうなので。

Contrast-A

IE対応

もうこの世から消し去りたいIE8とか9。だが、なかなか消えない・・・

IE対策 HTML5+CSS3でサイトを作ってみる

1) HTML5の反映

昔はhtml5.jsを使っていたようだけど、今はhtml5shiv.jsを使うようだ。Googleからとってくるのだ。

<!--[if lt IE 9]>
<script src="/js/html5shiv.js"></script>
<![endif]-->

2) IEの最新バージョンをレンダリング
  1)だけでうまくいかなかった・・・ということでメタ情報も(挿入する位置に注意しなければならないよう)

<meta http-equiv="X-UA-Compatible" content="IE=edge">

3) CSS3の適用

これでグラデーションとか角丸がいけるようになるらしい。
CSS3PIE

あとは旧ブラウザへの対応も見ておこう。

他にもあれば継ぎ足しておこう。

PostgresSQL覚書 関数の戻り値をレコードに

関数の戻り値というと、普通は1つの値なのだけれど、複数行とってきたいとか、テーブルとしてとってきたいとか思う。

問い合わせ言語(SQL)関数

を見ているとできなくないらしいけれど、

CREATE FUNCTION sum_n_product_with_tab (x int)
    RETURNS TABLE(sum int, product int) AS $$
    SELECT $1 + tab.y, $1 * tab.y FROM tab;
$$ LANGUAGE SQL;

で、LANGUAGEが「SQL」となっていて、「plpgsql」で作っているものだとRETURNSの後ろをTABLE(ほにゃほにゃ)に変えただけではうまくいかなかった。
戻り値が
sum | product
—–+——————
50 | aaa
66 | bbb

とかになってほしいんだけど、
sum_n_product_with_tab
———————–
( 50, aaa)
( 66, bbb)

になってしまって、せっかくTABLEにしている意味ないんじゃない?ということになった。

ふむ。どうすればよいのじゃ・・・

ということで、せめて複数行とってくることにしよう。

CREATE OR REPLACE FUNCTION hoge(parm_cd character varying)
  RETURNS numeric  AS
$BODY$
DECLARE
    ・・・・
BEGIN

  CREATE TEMP TABLE wk_master(code numeric(2,0))
  ・・・・
  RETURN QUERY SELECT code FROM wk_master;
  DROP TABLE wk_master;

END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100
  ROWS 1000;

RETURN QUERY・・・とすると、複数行で返してくれる。

今日はこの辺で終了。

PostgreSQL覚書 Backup&Restore

またあっという間に時が経った。
師走だ。

WindowsバッチでAサーバにあるDBをBサーバに移すことにした。

んで、とりあえずいろいろ参考にして作ったのが下の例。

まずはパスワードを設定しておいて、途中で聞かれないようにしてから・・・
pg_dump を使って D:\backup\test.backupに 111.111.111.111:5432 のA1_DBをバックアップ。
(ユーザはpostgres)
バックアップファイルからpg_restoreを使って、111.111.111.123:5432 のA2_DBへリストア。
(こっちもユーザはpostgres)

—————————————————————–
SET PGPASSWORD=password
“C:\Program Files\PostgreSQL\9.3\bin\pg_dump.exe” -f D:\backup\test.backup -i -v -h 111.111.111.111 -p 5432 -U “postgres” -Fc “A1_DB”
if not %ERRORLEVEL%==0 stop

“C:\Program Files\PostgreSQL\9.3\bin\pg_restore.exe” -c -h 111.111.111.123 -p 5432 -U “postgres” -Fc -d “A2_DB” D:\backup\test.backup

stop
—————————————————————–
オプション関連はドキュメントを見てもらえばいいと思うけど、書き順やらがドキュメントではいまいちわからんかったのでメモっとく。

SQLServer覚書 ストアド内で別のストアドを実行

ストアドプロシージャ内で、別のストアドプロシージャを呼び出す方法。

例えば、proc_GetEmployeeIn(引数:@bumon_cd) を呼び出して結果を取得する場合だと、
以下のように、あらかじめワークテーブルを作っておいてから、
INSERT INTO ワークテーブル EXEC プロシージャ名 引数1, 引数2 , …
というようになる。

CREATE TABLE #work_table (
      emp_cd VARCHAR(1000)
    , emp_name VARCHAR(10)
)
INSERT INTO #work_table EXEC proc_GetEmployeeIn @bumon_cd

PostgreSQL覚書 IsNumericとかIsNumberの代わり

いつのまにか10月になって、いつのまにかWordPressがVer4.0になってた。
時の経つのは早いもの。

PostgreSQLにはIsNumericとかIsNumberみたいな関数はないのねぇ・・・
Function作ればいいんだよ!って、言われてもねぇ・・・

ということで、代替案を漁ってみた。

SELECT (CASE WHEN emp_cd ~'^[0-9]*$' THEN emp_cd ELSE NULL END) emp_cd FROM master_table

ってな感じで、正規表現を使うらしい。
関数作って使ったほうが楽じゃね?って言わないでね・・・

PostgreSQL覚書 接続中を調べる

昔バグった話。
接続しっぱなしでロジックを終わらせてたら、どんどん接続数が増えて処理できなくなった。
CLOSEすんのを忘れてたんです。スイマセン。

で、大騒ぎになる前に。

SELECT * FROM pg_stat_activity
 ORDER BY usename,application_name;

で、ちゃんとクローズしたことを確認する。
application_nameがpgAdmin以外で、IPアドレスを確認して、current_queryがアイドル状態になっておらず、SQL文が設定されたままだとクローズしていない。
処理が終わってもこういうのが残っていると、ちゃんと切れてないので切断すること。

このバグのせいで、運用問題にまで発展しテンヤワンヤとなったので、メモ。

久しぶりの海外(台湾)

久しぶりって言っても2度目の海外、台湾!

Peachで関空から、さらば日本!いや、帰ってくるし。(仕事残してるし)
2014年9月から、離陸・着陸時でも通信していなければ電子機器が使えるようになり、カメラでカシャカシャとれるように。
といっても、台湾上空は撮影禁止だそうで撮れなかったのだが・・・

ピーチからKLM
ピーチからKLM

上空からみた台湾は、緑に囲まれた美しい国土(?)、まぁ美しい土地。
下手に開発されていなくて、田園地帯が美しいし、河川も堤防とか整備されているところが少なくてありのままな感。

まぁ、下手に開発して、住民増やそうと地名なんか綺麗にすると、例の広島のように被害が大きくなるような気がしないでもない。
(あんなところにどうして住むのだろう?人災だ!と言われてもしょうがない)
家の近所でも避難勧告が出てて、やっぱり崖関係。
昔から住んでるからといって、もう安心はできない。
斜面やら崖やら、そんなんが近くにあるようなところに住むというのは自殺行為だと思い知った今年の夏だった。

そんな話はともかく、とりあえず台湾。
どっかのページに英語が喋れればOKだよ、って書いてあったけど、結局緊急事態とか、困ったときには英語はどうにもならん。
(日本語のほうがまだ通じるって言われたが、結局使わんかった)
ちょっと中国語を勉強したところでどうにもならんのね。向こうが言っていることがわからないと、答えられないから。
参ったし、反省。やっぱり、ある程度言葉わかったほうがいいな。

ただ、台湾のいい人たちに、なんとかフォローしてもらった。
台湾人は全員優しいとは言わんが、助けてもらった人たちに感謝感謝である!

夜市やら市内観光やらしてみたが、もう少しゆっくりできればよいなぁと思った。
自転車とかでぐるっとまわってみたいのだ。
ということで、次回台湾旅行は、レンタル自転車を借りてグルグル回ってみるツアーにするつもり。

台北レンタサイクル
台北レンタサイクル

なんかカードが必要みたいなので、乗れるかどうかチェックしておこう。

食事はどうかといわれると、結局自分の好みの味ではなかった。
なんというか、キレがない感じ。
日本では薄味派な私だが、向こうでは物足りない。
日本の薄味って、薄いけどしっかりした感(塩分とかダシとか)があるのだが、台湾だと色は濃いけどだるーい感じ。

ただし、甘味はうまかった。
かき氷を食べたんだけど、なんか、蜜やら練乳やら、やたらいっぱいかけてくれるから、「やめてくれぇ~~~」とか思ったが、食べてみるとホントに絶妙な甘さでおいしかった。
あれはもう1度たべたいな。
豆花だっけ、まだ食べてないから、これも食べてみたいところ。

ということで、次回の台湾は、サイクリングと甘味処めぐりにしよう!

ExcelVBA覚書 誰かが使ってる・・・

Excelファイルを開く。
だけど、誰かが開いているから保存はできないよ。
だから処理をやめるね。

ってなことがやりたい!ということで調べてみた。
なんか、Open xxx For Append とか Open xxx For Binary とかで誰かがつかんでることを確認する方法とかあったのだけど、ファイルがちょっと特殊なところにあり、こういうことができない。
それに、パスワード設定しているため、誰かが使っているときにReadOnlyをFalseにして開くと、パスワードまで聞いてくる始末・・・
なので、脳みその10%をフル活用してみた。

'
' 引数で指定されたパスを開いて、開いたブックを返す
' (ここではパスワード設定は省略)
Private Function OpenBook(filePath As String, readonlyFlg as Boolean) As Workbook

    Dim fileName As String

    On Error Goto ErrorFunc

    '(1) とにかく読取専用で開く(確認メッセージとか出さない)
    Set OpenBook=  Application.Workbooks.Open(Filename:=filePath , UpdateLinks:=False _
                                              , Notify:=False, ReadOnly:=True)
    '(2) 読取専用で開くときはここで終わり
    If readonlyFlg Then Exit Function

    '(3) 開いたブックを読み書きできるようにする(確認メッセージとか出さない)
    fileName = OpenBook.Name
    OpenBook.ChangeFileAccess Mode:=xlReadWrite, Notify:=False

    '(4) なぜか、開き直しになり設定が切れてしまうので、もう一度設定しなおす
    Set OpenBook = Workbooks(fileName)

    '(5)ファイルが読取専用でなかったら、編集可能なブック!
    If Not OpenBook.ReadOnly Then Exit Funtion

    '(6) OpenBook.ReadOnly = True なら、誰かが掴んでる!=> 閉じる
    OpenBook.Close SaveChanges:=False
    Set OpenBook = Nothing
    Exit Function

ErrorFunc:

    '指定したパスのファイルがないときは、(1)でエラー発生し、ここに来る!

End Function 

ということで、回りくどいやり方をすれば何とかできることが分かった。
上の例だと、ファイルがないときも、開けないときもNothingで返してしまうので、区別したいときはフラグを返してやるとか工夫が必要。

ブックを開いた後は

    OpenBook.Windows(1).WindowState = xlMinimized

で最小化しておくと、画面のちらつきは最小限で済む。

で、これが「特殊な環境下」でうまく動くかどうかはまだ試せていない。

ExcelVBA覚書 AutoFilterまとめ

あぁ、フィルタよ、フィルタよ・・・
結構ややこしかったぞよ。

1つの列に対する複数条件の設定とか、フィルタ解除の方法やら、マクロの記録で出力されないロジックを調べるのに時間がかかった。

1) フィルタの解除

' フィルタが設定されていたら解除しちゃうよ
Private Sub ClearAutoFilter(target_ws as Worksheet)
    If target_ws.AutoFilterMode Then target_ws.AutoFilterMode = False
End Sub

2) 1つの列に対する複数条件設定

これが結構難しかった。というより、参考になるサイトがあまりなく、やっとこさで探し当てた。
別のところで配列(Variant型)を作っとく。
たとえば、
Dim arr As Varient
arr = Split(“あ,い,う”)
として、
SetAutoFilterAt Activesheet.Range(“A1:E100”), 1, arr
ってな感じで下のプロシージャを呼び出す。
すると、「あ」「い」「う」に該当するレコードが抽出される。

Private Sub SetAutoFilterOn(target_rng as Range, col as Long, crit_arr as Variant)
    target_rng.AutoFilter Field:=col , Criteria1:=crit_arr , Operator:=xlFilterValues
End Sub

試してないから、動かんかったらごめんなさい。
でも、イメージ的にはこんな感じで、Criteria1とOperator の設定がポイントということが分かった。

3) 絞り込んだデータの取得(A) 1行ずつ漁る

    Dim cnt As Long
    Dim rng As Range
    Dim target_rng As Range

    Set target_rng = Activesheet.Range("A1:E100")

    'target_rngの1行目がタイトル行なので、-1 する。
    With target_rng
        cnt = .Columns(1).SpecialCells(xlCellTypeVisible).Cells.Count -1
        If cnt > 0 Then
            For Each rng In .Columns(1).SpecialCells(xlCellTypeVisible).Cells
                'タイトル行以外で処理する
                If rng.Row > 1 Then
                    '抽出範囲の1列目の情報をダイアログ表示
                    Msgbox rng.Parent.Cells(rng.row,1).Value
                End If
            Next
        Else
            Msgbox "データなし"
        End If
    End With

ForEach文が1行ずつ見ているところ。
抽出範囲の1列目ってのが、Columns(1).SpecialCells(xlCellTypeVisible).Cells。

4) 絞り込んだデータの取得(B) ワークシート関数でドバッと集計

    Dim cnt As Long
    Dim target_rng As Range
    
    Set target_rng = Activesheet.Range("A1:E100")

    'target_rngの1行目がタイトル行なので、-1 する。
    With target_rng
        cnt = .Columns(1).SpecialCells(xlCellTypeVisible).Cells.Count -1
        If cnt > 0 Then
             '抽出範囲の2列目の合計を取得(タイトル行は数値でないこと)
             Msgbox  "合計:" & Cstr(Application.WorksheetFunction.Sum(.Columns(2).SpecialCells(xlCellTypeVisible).Cells))
        Else
            Msgbox "データなし"
        End If
    End With

他の内容は割と簡単に調べられるので省略。

改めてExcelVBAって奥深いなぁ・・・って思った。
ってか、マクロの記録でこういうロジックを残してくれたら、悩まずに済むのに!といつも思う。

ExcelVBA覚書 マクロの記述を削除する

Excelファイルを作成するときに、マクロの入ったシートをコピーして作成すると、マクロが残っちゃって困ってしまった。
おまけに、一部のシートしかコピーしてないから、モジュールとかにあるプロシージャとかがないってエラーになってしまう・・・

で、マクロは保存する前に削除しちゃいましょう!なロジックを見つけてきた。

元ネタはこちら
Excelでお仕事! マクロを除いた配布用ブックを作成する。

'======================================================
'ブック上にあるマクロを全部削除しちゃうよロジック
'======================================================
Public Sub DeleteMacroIn(wb As Workbook)
    
    Dim obj As Object    '正しい型はVBComponent
    Dim lines As Long 
    
    For Each obj In wb.VBProject.VBComponents
        With obj.CodeModule
            lines = .CountOfLines
            If lines > 0 Then .DeleteLines 1, lines 
        End With
    Next obj

End Sub

不惑

とうとう、そういう歳になってしまった。

が、迷い戸惑い、怒りに身を震わせる自分が相変わらずここにいる。

で、Agora 「不惑」という困惑 という記事を読んだ。

まぁ、歳なんて関係ないのよ。西洋にはそんな考え方ないし・・・みたいな感じ。
こういう考え方ができると楽だよねぇ・・・とか思うのだが、本当にそれでよいのかとも思う。

自分は独身で子供もいないけど、周りにいる同世代、または親である人たちで、そりゃいい親だとか、ちゃんと育てているなと思える人たちはいっぱいいるが、そうも思えない人もいる。
ほっときゃいいじゃない、って思うかもしれないが、ほっといて本当によいのだろうか。
放置して、自分に跳ね返ってきたら、あの時ほったらかしにしたことを後悔しないかね。
(まぁ、関係ないって思っているのだったら、後悔なんかしないのかもね。)

でも、マンションの隣の部屋で餓死した人がいたらどうかな。
なんかできなかったかな、自分・・・とか思うんじゃないの。

仏教には受容という言葉があるけれど、何でもかんでも受け入れるということではない。
やっぱり自分で考えて、人の意見も聞いて、かみ砕いて消化する必要があると思う。
そして、ダメなものは駄目だし、「ならぬものは、ならぬ」。

まぁ、そんな当てもなく、いろいろ思いつつ、今日は早く仕事を終わらせるのが、今の私のメイン課題なのである。

Excel覚書 Excelを複数バージョン入れているとき

ファイルをWクリックしたときにどっちのバージョンのEXCELを開いてほしいか指定する方法。

コマンドプロンプトで以下を実行

自分の環境はExcel2013(32bit)なので、

“C:\Program Files (x86)\Microsoft Office\OFFICE15\excel.e
xe” /regserver

ファイルパスは32bitと64bitでは違うし、パスを指定してインストールしたらこれとは違うので、自分の環境にあわせて変える。

Excel2003はOFFICE11、2010はOFFICE14、2013はOFFICE15。