今いる場所でコマンドプロンプトを開いてくれるBATファイルを作ってみた

やあ子供たち。今日はタイトルの通りの内容のメモだよ。以下のコードをcmd_here.bat という名前にでもしたBATファイルとして保存して、任意のフォルダにコピーして、これを実行してみよう。すると、その場所に最初からいる状態でコマンドプロンプト画面が始まるぞ!

@echo off
cmd /k "cd /D %~dp0"

地味に便利じゃないかこれ。
では今日はここまでだ。チャオ!

express.static() を先回りして特定のファイルの返送処理を自分ロジックで上書きしよう。

やあ子供たち。
express.static()は便利な反面、実際には何をやってくれているのかがブラックボックスになっているとも言えるね。
例えばあるコンテンツページを表示した際に、pngを返した枚数だけカウントしたいだとか、jpegは禁止するだとか、動画は当然ストリーミングで返してくれてるよね、え?まさか全部メモリに読み込んだバッファを返してるの?何してくれちゃってるの?という具合に、単純にexpress.staticに任せきりにしたくない場合というのは多々あるはずだ。
そんなときは、「expressのミドルウェアは、記述した順番に実行される」ということを利用して、例えば「png」で終わるリクエストURLだけ捕まえてその中でやりたい処理をやり、そこでレスポンスを終わらせてしまえばいいだけのことさ。あるいはここで、pngきたよとかログに追記したり、そのpngに何かをして、返したり(何何?)、いろいろできるってわけ。
それをやってみた具体的なコードが以下だよ。 

app.get("/*png",(req, res)=>{
  console.log(req.url);
  console.log("i have captured png req before express.static does.");
  var path = __dirname + "/static_resources"+ req.url;
  console.log( path);
  fs.readFile(path, (err, data) => {
    if (err) {
      console.log("file read error");
      // res.end();
    }else{
      console.log("hi, and im gonna write and send png for my own, not express.static");
      res.writeHead(200, { "Content-Type": "image/png" });
      res.end(data, 'binary');
    }
  });
});
app.use(express.static("static_resources"));

気を付けなければいけないのは、コンテンツは、express.staticのベースパス(上記一番下の行で指定しているよ)の中に実際には配置されているわけなので、上記pngの処理の中で、ちゃんとこのベースパスも入れた正しいパスをfs.readFileには渡してあげなくちゃいけないよねってことさ。
じゃ今日はこの辺で。(expressを知らないNodeJSだけの国からやってきたおじさんの今日の気づきでした。)
チャオ!

GoogleSpreadSheetの日付入力ショートカット

やあ子供たち、Excelで日付をショートカットキーで一発入力するのは「Ctrl+;(セミコロン キー)」で、超便利なわけなんだが、GoogleSpreadSheetを使っているときに、日付を入力したいというわけでそれをやろうとすると、ブラウザなだけに、画面の表示倍率が上がっていってしまうので、「あー、だめか、無理なのか」と思ってそのまま放置してしまっていたのだが、ちゃんと調べてみるとなんと「Ctrl+:(コロン キー)」で、日付が入力できるぞ!ちなみにExcelで「Ctrl+:(コロン キー)」を押すと、現在時刻を一発入力できてしまうわけなので、じゃあGoogleSpreadSheetでは、現在時刻は入力できないのか?というと、そんなことはなく、現在時刻入力のショートカットキーはずばり「Ctrl+Shift+:(コロン キー)」で入力が出来るぞ!

NodeJSだけでダウンロードサイトを作る

(後日記:やめておけ。expressすら導入もしないでNodeJSだけを使おうとするのは絶対にやめた方がいい。2024年5月某日)
やあみんな。NodeJS楽しいよねまじで。
今日はおじさんはExpressとか使わずにNodeJSだけでファイルをダウンロードできるサイトを構築するための最小限コードをメモしようと思うぞ。(Expressを使っているお友達はres.download()が使えるのでこの記事に用はないはずさ。この記事に用があるのはきっと何か特殊な事情があるお友達だけだと思ってる。(ようこそ!そういうお友達!おじさんもみんなの仲間だよ!))
それではさっそくやっていきましょう。

●まずはユーザーの目に触れる表側。サイトのページを作ろう。
例えば以下のようなHTMLを用意しよう。(部分によってコメントの文法表記が違うから面白いとおもうのはおじさんだけかな?(笑)青い字の部分な。)

<html lang="ja">
<meta charset="utf-8">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control"content="no-cache">
<head>
<style>
  /* スタイルシートコードを記述 */
</style>
</head>
<body>
  <!--HTML部品を設置-->
  <h1 id="hello">My公式サイト</h1>
  <a href="/hello_dlreq" >hoge_file.7z(最新版)</a>
  <script type="text/javascript">
  // 必要に応じてプログラムを記述
  </script>  
</body>
</html>

これを、some_index.htmlとして保存しよう。

●次に裏側のしかけ。サーバーサイドを記述しよう。
さあそして、サーバーにリクエストが来た場合の処理を記述した、サーバーサイドjavascriptのプログラムを書いていこう。それは以下のようなものになるよ。

const http = require('http');
const server = http.createServer();
const fs = require("fs");
server.on("request", (req, res) => {
    if (req.url.endsWith('/')) 
    {
      // 用意したHTMLファイルを描画
      fs.readFile("./some_index.html", function(e, buff){
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.write(buff.toString());
        res.end();
      });
    }
    else if (req.url.endsWith('_dlreq')) 
    {
      // some_index.html中の<a>タグリンクが押された時にダウンロード開始してあげる処理
      // 日本語ファイル名もいけるかな?→それは試してみてくれよな!
      var FileName = "hoge_file.7z";
      res.setHeader('Content-Disposition', 'attachment;filename*=UTF-8\'\'' + FileName);
      var filepath1 = __dirname + '/some_folder/'+FileName;
      fs.createReadStream(filepath1).pipe(res);;
    }
});
server.listen(3000, () => console.log('Server http://localhost:3000'));

これを、some_server.js として保存しよう。
あとは、some_folderというフォルダを作成し、その中に、みんなが今ダウンロードさせたいと思っているファイル、hoge_file.7zを置こう。
フォルダ構成はこんな感じになるぞ。

│ some_index.html
│ some_server.js
└─some_folder/
        hoge_file.7z

はい!まずは以上!。どうだえらくシンプルでまさに最小コードという感じじゃないかこれ。さらに説明が必要だと感じたときにはまた追記したいと思います。
ではまたな、チャオ!

ExcelVBA ブックが開かれた時に呼ばれる処理を書いてみたよ

やあ子供たち、今日はね、Excelを開いた途端に、自身のウィンドウサイズを所定の値にして、かつ、リボンが畳まれた状態になってくる、そんなVBAスクリプトを作ったので、そのやり方というか、自分用メモとして残します。
(※MS Office2019のみで動作を確認しております。)

Private Sub Workbook_Open()
    
    '本ブックが開かれた時に呼び出される固定関数の一つがこのWorkbook_Open()だ
    
    'リボンを畳まれた状態にする(トグルする効果があるようなので2回呼ぶ)
    Application.CommandBars.ExecuteMso "MinimizeRibbon"
    Application.CommandBars.ExecuteMso "MinimizeRibbon"
    
   'ウィンドウサイズを指定します
    Application.WindowState = xlNormal
    Application.ActiveWindow.Height = 380
    Application.ActiveWindow.Width = 400
    
End Sub

ちなみに以下コードは、VBAエディタ画面左のソースコード階層の中の、Sheetのとこではなく、「ThisWorkBook」となっているところにペーストすべきとされているので注意してくれ。Sheetのとこのソースコードにこの関数書いても動かないぞ。気をつけろ!
ほんとはウィンドウ位置も指定したいのだけど、ウィンドウがどっか行っちゃうんだよな。それはまた今度だ!
以上だよ、チャオ!

編集中のスライドに日付テキストボックスを挿入するPowerPointVBA

やあ子供たち。資料作ってるか。今日は今編集中のPowerPointのスライドの右上に、日付現在時刻テキストボックスを入れる便利スクリプトの紹介だよ。ボタンに紐づけてXLMファイルとして持っておけばいつでも使える便利ツールの出来上がりだ。
これはいろいろ調べて2時間くらいで出来たのだけどその中ではいろいろと勉強になった。

  • 現在編集中のスライドを取得するやり方
  • 便利なWith構文
  • WeekDay関数やWeekDayName関数
  • テキストボックスの挿入方法
  • スライドの幅の取得
  • フォント名の指定方法
  • With構文の中でもIf文などが普通に使えてしまうこと
  • 引数付きの関数は、UIから直接呼ぶことは出来ないこと

まそういったノウハウが、以下のコードを詰め込んであるのでよかったら参考にしてくれよな。
(※MS Office2019のみで動作を確認しております。)

Sub PPT_util_DateTag_common(Optional with_time As Integer)
  
    Dim ppApp As New PowerPoint.Application
    Dim ppPres As PowerPoint.Presentation
    Dim ppSlide As PowerPoint.Slide
    ' 現在編集中のスライドを取得する。
    Set ppPres = ppApp.ActivePresentation
    Dim slide_index
    slide_index = ppApp.ActiveWindow.Selection.SlideRange.SlideIndex
    Set ppSlide = ppApp.ActivePresentation.Slides(slide_index)
    Dim slide_width, box_width
    slide_width = ppPres.PageSetup.SlideWidth
    box_width = 220
    ' 日付ボックスをスライド右上に描画。
    Set shp = ppSlide.Shapes.AddShape(Type:=msoShapeRectangle, _
        Left:=slide_width - box_width, Top:=0, Width:=box_width, Height:=21)
    With shp.TextFrame2
        .TextRange.Text = Date & "(" & WeekdayName(Weekday(Date)) & ") "
        If (with_time > 0) Then
            .TextRange.Text = .TextRange.Text & Time
        End If
        .TextRange.Font.Name = "Meiryo UI"
        .TextRange.Font.NameFarEast = "Meiryo UI"
        .TextRange.Font.Size = 12
    End With
    ' 曜日ごとに色を変える
    Select Case Weekday(Date)
        Case 2
            shp.Fill.ForeColor.RGB = RGB(160, 30, 30) '月曜日
        Case 3
            shp.Fill.ForeColor.RGB = RGB(230, 180, 60) '火曜日
        Case 4
            shp.Fill.ForeColor.RGB = RGB(150, 200, 150) '水曜日
        Case 5
            shp.Fill.ForeColor.RGB = RGB(150, 120, 50) '木曜日
        Case 6
            shp.Fill.ForeColor.RGB = RGB(0, 20, 150) '金曜日
        Case Else
            shp.Fill.ForeColor.RGB = vbBlack
    End Select

End Sub

Sub PPT_util_DateTag()
    Call PPT_util_DateTag_common(0)
End Sub

Sub PPT_util_DateTagTime()
    Call PPT_util_DateTag_common(1)
End Sub

実際にどんな感じになるのかは、以下図をご参考下さい。
f:id:nurs:20211014115855p:plain
やーこれねー、どうよこれ。「私ずっとこういうの欲しかったの。」「私、ずっとこういうのが欲しかったんですっ!」って声がたくさん聞こえてきそうじゃないかこれ。おじさんはPowerPointファイルを日記代わりにしていて、テーマごとにあちこちに作ってるんだけど、この日付情報の入力を手動でずっとやってきたんだよね。いつか自動化したいなと思ってさ。
チャオ!

パワポのテキスト抽出VBA

パワーポイントファイルの中の、テキストを抽出するVBA。
フォントサイズが20以上のテキストを見つけたら、抽出。

Sub PPT_pdf()

   Dim ppt As New PowerPoint.Application
   Dim presen1 As PowerPoint.Presentation
   Dim save_path As String, file_name As String
   Dim Target As String
   
   'ターゲットファイルpptxを選択させて選択したファイルを開く
   Target = Application.GetOpenFilename("PowerPoint,*.pptx")
   If Target = "False" Then Exit Sub
   Set presen1 = ppt.Presentations.Open(Target, WithWindow:=MsoTriState.msoFalse)

   '結果出力用のテキストファイルを開く
   Dim fs As Object
   Dim stream As Object
   Set fs = CreateObject("Scripting.FileSystemObject")
   Set stream = fs.OpenTextFile("d:\extracted_text.txt", 2, True)
   
   '各スライドを探索し、フォントサイズが20以上のテキストがあれば
   '結果出力用のテキストに書出し
   For Each sl In presen1.Slides
     stream.Write "slide-" & sl.SlideNumber
     stream.WriteLine
     For Each shape1 In sl.Shapes
       If shape1.HasTextFrame Then
         If shape1.TextFrame.TextRange.Font.Size >= 20 Then
            Dim txt As String
            txt = shape1.TextFrame.TextRange.Text
            stream.Write txt
            stream.WriteLine
         End If
       End If
     Next
     stream.WriteLine
   Next
   stream.Close
   
End Sub