Excel VBA 業務に使われているか

絶対に使われてるが、検索してヒット数を見た。

Googleで検索した件数が見える。
プログラム言語としては、Javaが6百万件。
VBAとPythonが百万件。Rubyが何と4百万件ある。
さすが、島根県から生まれた言語。

以上、ほぼこの結果かな。サイトの数の結果ね。
私の場合は業務という日本語があるのが違う。

VBAは、Visual Basic言語のこと。

「VBA 業務」の2倍ある。
Excelを付けて検索すると

 

プログラム言語って何でもええか

オブジェクト指向を知るならJavaとかRubyとか。
学習のために言語を選ばないといけないと思っていた。
プログラミング言語のランクを調べるプログラミング言語のランク)と
10年前はJavaやCとC++言語で50%以上あった。
今はどれも10%程度。バラけてきた。
戦国時代なんでしょうか
その都度、目的に合わせて言語を選択するようになったのだろうか?

プログラムは道具
目的があっての道具
道具は使う必要があって学習効果が上る

英語も外国に行って目の前の(仕)事に集中しながらも、必要にせまられ伝わる「ことば」をしゃべることで英語も上達する

プログラミングでわからないことがあれば調べる。
英語も伝わるか試行錯誤、いろいろ言う、試すことで身になる。
話せば、
目の前に答えてくれる人がいる。行動が大事。行動すると覚えやすい。

網羅的にプログラムを学習してからプログラミングすることはない。
やってて解らないことがあると調べる。
入力すれば、
目の前のコンピュータから答えが見つかる。
行動が大事。行動すると覚える。

これ普通
私は、今もしてる。
おじいちゃんだからその都度法だわ。

動画の分割や変換、結合コマンド 、高速再生、音声追加、ffmpeg.exe

マウス操作よりコマンドラインで操作の方が簡単
と思う。
分割や変換できるソフトをインストールして使うと
使い方はマウス操作だから変化を見ながら操作する
ヘルプを見ない質なのでしかたないが、難しい。
また、インストールしたアプリ名と分割や変換の機能があるかどうか連想できないのも問題だ。
つまり、
コマンドラインでの入力の方が慣れている世代なのです。

もともと、EverNoteに動画を置くのにサイズの問題があった。有料でも200MBまで。分割できるのだが、ffmpeg -i org.mp4 new.mp4とするだけでnewの方が半分になるので使っていた。

インストールというかファイルを取ってくる

さて、ffmpeg.exeはここから手に入れる。
https://www.ffmpeg.org/
手順は、以下。

  1. ダウンロードの英語(次図は翻訳)の文字画像をクリック
  2. ウインドウのマーク、画像(文字でない)をクリック
  3. ここでは下側の「BtbN」をクリック

令和6年1月11日時点

(tar.bz2?実際ダウンロードファイルはzipだった)
zipファイルを解凍するとbinフォルダに3つのファイルがある。

ffmpeg-master-最新-win64-gpl.zipを選ぶ。解凍してbinフォルダに以下の3つがあればok。このffmpeg.exeファイルはサイズは大きいがこの


.DLLの拡張子のファイルが別に必要な「Linking」とか「Shared」ではなく、Staticを選択する。Static付きのファイルが無かったらShared無しを選ぶ。

解凍した状態で以下のようにLibフォルダがあり、.DLLなどがいっぱいあるならffmpeg.exe単体では動かない。

以下のようにLibフォルダがあるとffmpeg.exeの他に必要なDLLもコピーする必要がある。ffmpeg.exeファイルのサイズは、200kB以下と小さいのでffmpeg.exe単体では動かない。

以下ならコピーするファイルが多くなる。ファイル名にsharedって付いてます。

\は¥のこと
ffmpeg.exeをc:\windowsフォルダに入れておくとどのフォルダからも実行できるが、削除したくてもどれかわからなくなる。
とりあえず、自分しか使わないから以下に置く。
C:\Users\take\

以下は使い方。
一度ffmpegを実行すると圧縮されるようだ。時間を指定するので一度ffmpegを実行する。
開始時間0秒から最後までa.mp4をb.mp4に出力する。

C:\Users\take>ffmpeg.exe -ss 0 -i a.mp4 b.mp4

C:\Users\take>ffmpeg.exe -ss 0 -i 入力ファイル  出力ファイル

分割

分割スタート(-ss 10)から1分(-t 60)まで。-tは-sの開始からどれだけ記録するか時間を入れる。-iで元の動画。出力先の動画は最後。50秒の動画ができます。

C:\Users\take>ffmpeg.exe -ss 10 -i 0.mp4 -t 60 1.mp4
 
-tは終了時間をメモしてスタート時間から引き算しないといけまえん。2回ffmpegを実行する必要はあるが、-to 00:01:25だと始めから1分25秒までの動画ができますので、もう一度-tを省略して-ss 00:00:10とすると開始10秒まえをカットした動画が得られます。
 
分割:1分から最後まで -tは無し。最後まで
C:\Users\take>ffmpeg.exe -ss 60 -i 0.mp4  2.mp4
.mp4ファイルのファイル名は、日本語は化けたりしてコマンド自体実行できなかったりなので適当な数字の名前0.mp4とか1.mp4などにしている。
変換:mp4からaviへ
C:\Users\take>ffmpeg.exe -i 0.mp4 0.avi
拡張子を変えるだけ。
 
C:\Users\take>ffmpeg -ss 開始秒 -i 入力ファイル -t 長さ(秒) 出力ファイル
 
-iの秒の開始を5分後とする場合は00:05:00が使える。-tの長さも2分なら00:02:00と書ける。
C:\Users\take>ffmpeg.exe -ss 00:05:00 -i 0.mp4 -t 00:02:00 1.mp4
それにしても、先に1度だけffmpegを実行して圧縮してから時間は決めた方がいい。

AviUtlでファイルを結合/追加読み込みすると「映像の音ズレ」をおこすことがある。解決策はいろいろあるようだがこのコマンドを使うのが簡単。

結合

結合したいファイルが1.mp4、次に2.mp4の順。以下のテキストファイルを作る。これ作らない方法は見つからない。

file 1.mp4
file 2.mp4

C:\Users\take>ffmpeg -f concat -i a.txt -c copy out.mp4

動画の種類を変える

エンコーダ、動画の種類を変えるのは、拡張子を指定するだけ。

ffmpeg -i aa.avi aa.mp4

VOBファイルもできる。変換ツールを求めて色々インストールする必要はありません。「vob mp4 変換」って検索してもffmpegはなかなか出ません。「動画変換フリーソフト」では何とか見つかるかどうかです。

スピードを早く、遅く

スピードを早くしたり、遅くしたり。ここでは1.5倍速の例

ffmpeg -i src.mp4 -vf setpts=PTS/1.5 -af atempo=1.5 dest.mp4

1.5を0.8にすれば遅くなる。

音声の追加はこちら(m(__)m)にあります。in.m4aが音声です。

ffmpeg -i in.mp4 -i in.m4a -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 output.mp4

ほんま何でもできるんね。上下、左右反転回転もね。

エクセルを使った一括処理例

robocopy

Windows7の話で、使えた。
ロボットのコピー?
xcopyよりいい。

以下 コマンドプロンプト————

C:\Users\user1>robocopy
—————————————————
   ROBOCOPY     ::     Windows の堅牢性の高いファイル コピー
—————————————————–
  開始: Fri Sep 15 04:35:34 2017

簡易な使用法 :: ROBOCOPY コピー元 コピー先 /MIR

コピー元 :: コピー元ディレクトリ (ドライブ:\パスまたは \\サーバー
\共有\パス)。
コピー先 :: コピー先ディレクトリ (ドライブ:\パスまたは \\サーバー
\\共有\パス)。
/MIR :: 完全なディレクトリ ツリーをミラー化します。

詳細な使用方法については、ROBOCOPY /? を実行してください。

**** /MIR はファイルをコピーできるだけでなく、削除もできます。

—————————————————-
で、
サーバーにあるファイルで、追加したファイルだけをコピーしたい。
コピー先の自分のデスクトップで使っているファイルは変更したくない。

以下 コマンドプロンプト————
C:\Users\user1>robocopy /?
省略

                /XC :: 変更されたファイルを除外します。
                /XN :: 新しいファイルを除外します。
                /XO :: 古いファイルを除外します。
                /XX :: コピー先にだけ存在するファイルとディレクトリを除外し
                       ます。
省略

—————————————————-
というのがある。

書式は、
robocopy コピー元 コピー先  /スイッチ

robocopy \\XXXXsvr\readonly\data %HOMEDRIVE%%HOMEPATH%\Desktop\data\  /xo /s
/xoでコピー先の方が新しい場合はコピーしない。
/sでサブフォルダも
%HOMEDRIVE%%HOMEPATH%は、C:\Users\user1。コマンドプロンプトを起動したら開くフォルダ。ここにデスクトップdesktopもある。

エラーがあったとき、1秒待つ場合は/w:1。失敗したら繰り返し1回 /r:1でエラーでも次の処理になり続行する。/NP で進行状況なし – コピーの完了率を表示しない。

あまりにエラーが多いと余計なコピーがあったりした。
xcopy 元 先 /s /h /c /r /q /c /y
でもええかな。

Windows shutdown ある時間を指定

コマンドプロンプトで
C:\Users\username>aa.bat 17 5
と打てば17:05分にシャットダウンするようなバッチファイルを作った。
参照サイトは、3つ。
計算については、
set /a 計算式
説明はここ

文字の切り出しは、ここ。でも、つぎのサイトで解決。

以下をaa.batファイルにコピペする。元はここ

@echo off
set date_tmp=%date:/=%
:dateコマンドの出力をdate_tmpに入れる。C:\>echo %date:20=%で2018/11/16が18/11/16になる。ここでは%date:/=%なので2018/11/16が20181116になる。参考
set time_tmp=%time: =0%
echo date_tmp:%date_tmp%
echo time_tmp:%time_tmp%

 

set yyyy=%date_tmp:~0,4%
set yy=%date_tmp:~2,2%
set mm=%date_tmp:~4,2%
set dd=%date_tmp:~6,2%
set hh=%time_tmp:~0,2%
set mi=%time_tmp:~3,2%
set ss=%time_tmp:~6,2%
set sss=%time_tmp:~9,2%
set datetime=%yyyy%%mm%%dd%%hh%%mi%%ss%%sss%
set /a hh=%1-hh
echo hh:%hh%
set /a hh=hh*60*60
set /a mi=%2-mi
echo mi:%mi%
set /a mi=mi*60
set /a sss=hh+mi
echo %sss%
shutdown /s /f /t %sss%

不要な部分をカットするのと、
07や08と0ゼロから始まる文字列は、8進数と判断する。
0xだと16進数。set /?参照
だから、
先頭に1を付け加えてから100を引いている。
set /a hh=1%hh%-100
(10時以降ならこの計算式はいらない。気づかんかった。)
aa.bat—————————————

@echo off
set date_tmp=%date:/=%
set time_tmp=%time: =0%
echo date_tmp:%date_tmp%
echo time_tmp:%time_tmp%

 

set hh=%time_tmp:~0,2%
set mi=%time_tmp:~3,2%
set /a hh=1%hh%-100
set /a hh=%1-hh
echo hh:%hh%
set /a hh=hh*60*60

 

set /a mi=1%mi%-100
set /a mi=%2-mi
echo mi:%mi%
set /a mi=mi*60

 

set /a sss=hh+mi
echo %sss%
shutdown /s /f /t %sss%
————————————————–
実行前にa.batですぐにシャットダウンをキャンセルできるようにする。
動作確認でいちいちshutdownを入力するのは面倒だから。
a.bat——————————————

shutdown -a
————————————————-
シャットダウンのキャンセルは、aを入れるだけ。

aa.batの実行は、コマンドプロンプトで以下を入力
aa.bat 17 5
17の前後は半角のスペースが入る。
17と5は、17:05という意味だが、引数はスペースを挟む。
引数は2つ受け取るようになっている。
%1と%2
set /a hh=%1-hhで今の時間から何時間後か計算できる。
set /a mi=%2-miで今の時間
引数以外は、変数は%で囲む。
実行すると以下のような感じだ。

C:\Users\watanabe>aa 17 30
date_tmp:20170820
time_tmp:12:43:44.41
hh:5
mi:-13
17220

17:01マイナス今の時間=17220ミリ秒
昼頃実行したら17220ミリ秒後が17:05

なんでタスクスケジューラーを使わんの?
管理者権限でログインできないPCで使いたかったため。
で、
いつも決まった時間の場合は、引数も含めたバッチファイルを作る。
bb.bat———-
aa.bat 17 20
——————
実行は、bbエンター キー。

 

settimer() killtimer() WindowsAPIである時間にWindowsがVBAの関数(TimerProc)を呼び出す

ExcelのVBAでもWordのVBAでもできます。

以下を標準モジュールに書く。

Option Explicit

#If VBA7 And Win64 Then
'64bit版
   Private Declare PtrSafe Function SetTimer Lib "user32" _
   (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr, ByVal uElapse As LongPtr, ByVal lpTimerFunc As LongPtr) As LongPtr
#Else
 '32bit版
  Private Declare Function SetTimer Lib "user32" _
  (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
#End If
#If VBA7 And Win64 Then
 '64bit版
  Private Declare PtrSafe Function KillTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr) As Long
#Else
 '32bit版
  Private Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
#End If

'Windowsが呼び出す関数。引数や戻り値は決まっている。TimerProcで検索すると見つかる
Public Sub TimerProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal TimerID As Long, ByVal TickCount As Long)
  Debug.Print hwnd, Msg, TimerID, TickCount
  KillTimer 0, TimerID 'タイマーを止める。Windowsに教える。
'ここにやりたことを書く
End Sub

Sub main()
  SetTimer 0, 0, 1000 * 2, AddressOf TimerProc '1000で1秒。2秒後にTimeProcを呼び出す
End Sub

二秒後にイミディエイトウィンドウに出力する。イミディエイトは下の方の図の下の方。

もし、二秒にしたいならTimeProc関数のKillTimerの行をコメントアウトか削除する。

1列目はウィンドウハンドル、2列目は275はWM_TIMER = &H113 のこと。3列目は、タイマーID。4列目はWindowsの起動からの経過時間(ミリ秒単位)

これやって何がうれしいのかというと、一定時間後に実行する関数が作れる。
呼び出しを実行するのはWindowsのOS。だからVBAのリソースは使わない。Excelのプロセスとは違う。WordとExcelが動いていて、Wordが固まってもExcelまで影響を受けないのと同じ。ただし、WordとExcel間で通信?していると少し違うが、基本的にWordを閉じたらExcelは普通に使える。これはWindowsOSとExcel間でも同じです。ただ、WordとExcelは同等のアプリですが、WindowsとExcelはWindows管理下にある。このイメージ、メモリ空間かな。常にWindowsは動いている。「windows メモり 空間  64」で検索するといろいろ図が見えるが、仮想のメモリ状態、物理的/実際のメモりアドレスはありません。仮想のメモリ上は常にOS(Windows)が常駐してアプリが切り替わる。

で、

一定時間後に実行する関数は、TimerProc関数。
TimerProcの関数名はaaa関数でも何でもいいが、戻り値や引数の数、型は決まっている。

だって、

Windowsが呼び出すのでその決まり引数の数や型、順番も、あとは戻り値の型に従う。WindowsがExcelのプロセスの関数を呼び出す。
TimerProcの関数名をSettimerの第四引数に指定。
関数名を渡すのではなく、関数があるアドレスを渡すためAddressOf演算子を使う(メモリ上のアドレス/番地を渡すので関数名は関係ない。だからaaa関数でもいい)。

ExcelWordのApplication.OnTimeと同等のことができる。こっちは時間の間隔では無く実行する時間を指定する。5秒後にするには「今の時間+5分」。VBAのコードならNow() + TimeValue(“0:0:5”)。