2022年5月23日月曜日
LG PCモニタのスタンドを完全撤去する(破壊)
2021年9月1日水曜日
GASで気象庁XMLをパースしてLINE公式アカウントでブロードキャスト(全員へ送信)する
LINE公式アカウントを導入検討している自治体などが喜んで、
ソフトベンダーが泣きそうな記事ですが…
基本的に、掲題のことは完全無料でできます。
LINEチャンネルアクセストークンの取得
ここ、まだ完全に理解していないので、後ほど記事更新しますが、
- チャンネルアクセストークンv2.1⇒セキュリティ高いが実装難しい
- 長期のチャネルアクセストークン⇒とりあえずこっちでOK
以下URLを参考に、トークン(文字列)をゲットします。
https://developers.line.biz/ja/docs/messaging-api/channel-access-tokens/
GASスクリプト
main.gs
function pullHeadlineAndSend() { var url = 'http://www.data.jma.go.jp/developer/xml/feed/extra.xml'; var xml = UrlFetchApp.fetch(url).getContentText(); var xmlDoc = XmlService.parse(xml); var rootDoc = xmlDoc.getRootElement(); var nsDefault = XmlService.getNamespace("", 'http://www.w3.org/2005/Atom'); var entries = rootDoc.getChildren("entry", nsDefault); var length = entries.length; var currentDate = new Date().getTime(); var title, updated, date, author, content; var headlines = ""; // 最長で10分後に更新される var past10Min = 10 * 60 * 1000; // 10分以内に更新された東京都の気象警報のみ取得 for(var i=0; i < length; i++) { title = entries[i].getChildText("title", nsDefault); author = entries[i].getChild("author", nsDefault).getChildText("name", nsDefault); content = entries[i].getChildText("content", nsDefault); updated = entries[i].getChildText("updated", nsDefault); date = new Date(updated).getTime(); if(currentDate - date > past10Min) continue; if(title.indexOf("気象警報・注意報") != -1 && author === "仙台管区気象台" && content.indexOf("宮城県") != -1 ){ headlines += Utilities.formatString('[%s]\n%s\n%s\n', title, toLocalDate(updated), content); } } if(headlines !=="") { sendPushMessage(headlines); Logger.log(headlines); } } function toLocalDate(dateString) { var date = new Date(dateString); var formattedDate = Utilities.formatDate( date, 'Asia/Tokyo', 'yyyy年M月d日 HH時'); return formattedDate; } function testSend() { sendPushMessage('test message'); }
line_functions.gs
const TOKEN = 'got_token_string_ゲットしたトークンの文字列を貼り付け'; function sendPushMessage(text) { var url = "https://api.line.me/v2/bot/message/broadcast"; var headers = { "Content-Type" : "application/json; charset=UTF-8", 'Authorization': 'Bearer ' + TOKEN, }; var postData = { "messages" : [ { 'type':'text', 'text':text, } ] }; var options = { "method" : "post", "headers" : headers, "payload" : JSON.stringify(postData) }; return UrlFetchApp.fetch(url, options); }
2021年1月3日日曜日
bashのaliasでexpectを登録→シングルクォーテーションをエスケープし、別セッションでも有効にする方法
LinuxのGUIで複数タブ又は複数ウィンドウ(別セッション)で端末を開きつつ、各画面で臨機応変にサーバーにSSH接続する場合(どんな仕事だ…)、SSH接続をexpectのワンライナーでalias登録すると素早さが増しますが、躓いた部分があったので解説します。
aliasでシングルクォーテーションをエスケープする方法
bashでシングルクォーテーションをエスケープするには「\」=バックスラッシュ(日本語環境では¥マーク)を使用しますが、シングルクォーテーションの中のシングルクォーテーションには使えません。aliasコマンドは、登録するコマンドをシングルクォーテーションで囲む必要がありますが、expectをワンライナーで登録する場合、その内部にシングルクォーテーションを使う場面が出てきます。
この場合、一旦シングルクォーテーションを区切る意味で、「'\'」を使用します。
bad!!
alias 'a1=expect -c \'spawn .....\''
good!!
alias 'a1=expect -c '\''spawn .....'\'''
.bashrcを更新する方法
aliasコマンドでaliasを登録した場合、別セッション(=GUIでは端末の別タブ・別ウィンドウ)を開く場合、aliasを引き継いでくれません。別セッション立ち上げ時はユーザー・ホームディレクトリにある.bashrcを読み込むので、ここにaliasを記載しておけば事足ります。(OSによっては、.bash_aliasesへの記載が推薦されていることもあります)
しかし、
- 毎回ログインするサーバーが違う
- サーバーが不定期にクリーンアップされる
場合、.bashrcを編集するのは不適切です。そこで、aliasで登録した後、aliasの内容を.bashrcにリダイレクトしてやると、それ以降の端末起動時にも読み込ませることができます。
alias >> ~/.bashrc
前回alias登録済みで、重複があった場合、aliasのショートカットが上書きされるだけなので、.bashrcが無限増殖することはありません。
上記2つをまとめてワンライナーで
さらに、サーバー上に設定ファイルが置けない、毎回ログインするサーバーが不定の場合、alias登録から.bashrc更新までワンライナーで記載して、端末へコピペするとその後の作業が楽になります。
例として、複数のサーバーログインショートカットを作成し、.bashrcを更新するワンライナースクリプトを示します。
alias at='expect -c '\''spawn ssh -o UserknownHostsFile=/dev/null -o StrictHostKeyChecking=no username@192.168.0.1; expect "assword"; send "password\r"; interact'\''';alias ax='expect -c '\''spawn ssh -o UserknownHostsFile=/dev/null -o StrictHostKeyChecking=no username@192.168.0.100; expect "assword"; send "password\r"; interact'\''';alias >> ~/.bashrc;
これで、sshでパスワードを打っている隣の同僚を、置いてけぼりにすることができるでしょう!
2020年12月14日月曜日
Windows10で、レジストリを編集してキーの入れ替えを行う
ノートパソコンのキーボードや、コンパクトタイプのUSBキーボードでは、よく使うキーが、ファンクションキーと同時押しだったり、無かったりして不便なことがあります。
そこで、あまり使わないF11やF12、PageDown等を、InsertやHome等として使用する方法を紹介します。
Microsoft PowerToysを使う
PowerToysは、Microsoft製便利ツールの詰め合わせです。上級者向け・ベータ版のため、GitHubから手動でインストールする必要があります(リンク)。
こちらはWindows PCで、INSを殆ど使わないので、何故か特殊キーとなっているDELを割り当てて使いやすくしています。キーは何個でも割り当て可能です。
他にも、右クリックで画像縮小できるツール(画像のアップロード容量制限があるときにサッと縮小できる)があり、なかなか便利なツールです。
レジストリを編集する
PowerToysのインストールが出来ないが、管理者権限がある場合(そんなことは稀ですが、GitHubへの接続を禁じている等)、レジストリを編集することでキーの入れ替えが可能です。
ただし、表記が見辛くメンテナンスが面倒なため、ベターな方法ではありません。
まず、レジストリの下記ディレクトリを探し、
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout
「新規」→「バイナリ値」で新しい値を作成して、名前を「Scancode Map」とします。ここに、バイナリ値を書き込みます。
フォーマットは、
00 00 00 00 00 00 00 00 ←固定
[num] 00 00 00 [after] [before]
[after] [before] ....
00 00 00 00 ←固定
[num]は入れ替えたい組み合わせの数ですが、最後の00 00 00 00も含めるため、
+1の値を記入します。
[after][before]にはキー特有のコードを入力しますが、逆表記とします。
例えば、F12のコードは58ですが、00 58の逆で、58 00となります。
Page Down E0 51
Insert E0 52
F12 58
(今回使用したコードです。キーボードタイプによって変わるキーもあるので、Microsoft等のオフィシャルな情報を参考にしてください)
今回は、Shift & Insertで貼り付けを多用し、Page Downキーが無い外付けキーボードにも
対応するため、Page Down -> INS, F12 -> INS へ二つ入れ替えます。
00 00 00 00 00 00 00 00
03 00 00 00 52 E0 51 E0
52 E0 58 00 00 00 00 00
これで、Page Down / F12 が両方ともINSキーとなり、Shiftと組み合わせると貼り付けが可能となります。
Ctrl & V だとコマンドの中止となってしまうLinuxのために、INSが無いキーボードは「注」と大きく表記してほしいものですね。
2020年10月8日木曜日
Selenium+PythonでWeb操作を自動化する→実例:LINEモバイルの複数アカウントの月額料金を自動取得する
2020年9月14日月曜日
PowerShellでClassを利用する ver.2.0~文字コード指定、ルートタグ追加し、パース可能なxmlファイルを出力するクラス
前回の記事でXMLファイルを作成するPowerShellのClassを紹介しましたが、あれには重大な欠点がありました。
XML宣言は書きましたが、タグを羅列するだけで、ルートタグは特に作成しませんでした。これでも大丈夫かと思っていましたが、PowerShellやPythonのXML Parserでは、ルートタグが無いとエラーを吐いて、読み込んですらしてくれないのです(ただ、キーと値のデータを保存したかっただけなのに…)。
もう一点、文字コードも明確にUTF-8で指定しないと、PowerShellの標準はUTF-16なので、XML宣言と相違が出ることになります。
ルートタグで囲うので、データを保持するハッシュテーブルと、最後にセーブする関数を追加してクラスを再作成します。
仕様
- PowerShellでタグと値を指定して、XMLファイルを作成する
- ルートタグを指定して、保存時に全てのタグを囲う ←追加
- 文字コードをUTF-8にする ←追加
クラス
class xmlFile { $values = @{}; $override = $false; [void]SetOverride($set_boolean){ $this.override = $set_boolean; } [void]AddVal($key, $val){ if(!$this.values.Contains($key)){ $this.values.Add($key, $val); }elseif($this.override){ $this.values.$key = $val; } } [String]GetVal($key){ return $this.values.$key; } [void]SaveXml($root_tag, $save_filename){ '<?xml version="1.0" encoding="UTF-8" ?>' | Out-File $save_filename -Encoding utf8; "<$root_tag>" | Out-File $save_filename -Append -Encoding utf8; $this.values.keys | Sort-Object | ForEach-Object{ $set_value = $this.values.$_; "<$_>$set_value</$_>" | Out-File $save_filename -Append -Encoding utf8; } "</$root_tag>" | Out-File $save_filename -Append -Encoding utf8; } }
関数AddValでハッシュテーブルvaluesにキーと値を追加します。変数overrideの値によって、同名キーがある場合に無視するか、値を更新します。
キーと値はハッシュテーブルに格納し、関数SaveXmlによってXML宣言とルートタグを追加して保存します。いちいち保存しなくていいようにしたかったのですが、ルートタグの追加には必須です。
文字列をそのままパイプでOut-Fileに流してやれば、ファイルに保存できます。オプション -Appendでファイルに追記、-Encodeでエンコードを設定できます。
ハッシュテーブルのkeysを、Sort-Objectを介してForEach-Objectに渡すと、キー名アルファベット昇順で処理できます。
使用例
$xf = New-Object xmlFile; $xf.AddVal("testKey1", "testVal1"); $xf.AddVal("testKey2", "testVal2"); Write-Output $xf.GetVal("testKey1"); $xf.SetOverride($True); $xf.AddVal("testKey1", "testVal1-1"); $xf.SaveXml("parent", "C:\myCodes\test.xml");
↓結果
2020年7月11日土曜日
PowerShellでClassを利用する~keyとvalueの単純なxmlファイルを出力するクラス
class xmlFile { $newFile; # ->newFileNameにしてしまいそうだが、そこはオブジェクト志向で… xmlFile($setFileName){ $this.newFile =New-Item $setFileName -type file -Force; Write-Output '<?xml version="1.0" encoding="UTF-8" ?>' | Add-Content $this.newFile -Force } add($key, $val){ Write-Output "<$key>$val<⁄$key>" | Add-Content $this.newFile -Force } } $xf = New-Object xmlFile("$PSScriptRoot\test.xml"); $xf.add("testKey1", "testVal1"); $xf.add("testKey2", "testVal2");
↓出力(スクリプトと同じ場所に、test.xml)
クラスの宣言
メソッド
クラスの使用
その他

2020年5月24日日曜日
PythonとPowershellでgrep的処理を行う
FukushimaServer,192.168.10.2 SendaiServer,192.168.120.3 TokyoServer,192.168.1.1
Linux grepでファイル内の文字を検索する
grep "SendaiServer" sample_server_list.txt | cut -d , -f2
Python版
myPath = "C:/myApps/python/sample_server_list.txt" with open(myPath, 'r', encoding='utf-8') as file: lines = file.readlines() for line in lines: if line.startswith("SendaiServer"): address = line.strip().split(",")[1] print(address)
PowerShell版
$finder = Select-String -Path $PSScriptRoot\sample_server_list.txt -Pattern "SendaiServer"; $address = $finder.line.Split(",")[1]; Write-Output $address;
Select-Stringはgrepと同じような動作をしますが、帰ってくるのはオブジェクト(MatchInfo Class)なので、その中のlineを抜き出して、Splitする必要があります。
2020年5月22日金曜日
RLoginを使用し、ワンクリックでサーバー接続→SSH認証を行う
Server Entryの登録
スクリプトの作成
Document.Open(); wait(CONNECT); sopen(OPEN_LOOK); swait(3,">"); sputs("ssh SSH_Server_Name\n") swait(3,":"); sputs("myPassword\n"); swait(3,"Do you access this server(yes/no):"); sputs("yes\n"); sclose();
【解説】
- swait(3,">") : プロンプト文字列「>」が出るのを3秒待ちます。
- sputs("ssh SSH_Server_Name\n") : swaitでプロンプトが出るのを待った後、文字列を入力します。sshコマンドや、ユーザー名、パスワード等。最後に改行コードを入れると、エンターキーを押す挙動になります。
RLoginをEntryで自動接続するスクリプトの作成(VBS/PowerShell)
VBSの場合
Dim myShell Set myShell = CreateObject("WScript.Shell") myShell.Run "C:\Tool\RLogin.exe /entry Entry_Name" , 1, true
PowerShellの場合
& C:\Tool\RLogin.exe /entry Entry_Name
2020年5月21日木曜日
Powershellでフォルダ内のdocファイルを開き、CustomPropertiesを取得する
コード
$getProperties = @('myId', 'myNetwork'); $binding = "System.Reflection.BindingFlags" -as [type]; $word = New-Object -ComObject word.Application; $word.Visible = $False; $targetFolder = '\\QNAP\myData'; $docs = Get-ChildItem $targetFolder -Filter *.doc; foreach($doc in $docs){ $Document = $word.Documents.Open($doc.FullName, $False, $True); #fileFullName, Convert Dialog, Read-Only $customProperties = $Document.CustomDocumentProperties; $getValues = @{}; foreach($prop in $getProperties){ $myProp = [System.__ComObject].InvokeMember('Item', $binding::GetProperty, $null, $customProperties, $prop); $myVal = [System.__ComObject].InvokeMember('Value', $binding::GetProperty, $null, $myProp, $null); $getValues.Add($prop, $myVal); } $Document.Close(0); #0:Don't save, -2:Prompt, -1:Save $outputString = $doc.FullName + ">" + $getValues['myId'] + ">" + $getValues['myNetwork']; Write-Output $outputString; } $word.Quit(); $null = [System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$word); [gc]::Collect(); [gc]::WaitForPendingFinalizers(); Remove-Variable word;
解説
- $getProperties … 取得したいCustomProperty名を指定する
- $Document = $word.Documents.Open($doc.FullName, $False, $True)→Excelの場合はfileを指定すればいいのですが、何故かWordはFullName指定
- $getValues … foeachで回して、CustomProperty名を取得し、値を取得(見つからない場合などエラー処理を必要に応じて追加してください)
- $Document.Close(0) … 変数に入れたので、Wordファイルは閉じてOK。0は保存しない
- $getValues[プロパティ名] … これで値が利用できます
\\QNAP\myData\a1.doc>500604>10.56.135.12 \\QNAP\myData\a2.doc>500607>10.56.145.12 \\QNAP\myData\a3.doc>500609>10.72.136.11
2020年5月17日日曜日
SSH login without inputting password : expect oneliner ワンライナーでexpectを使ってsshログインする
- 公開鍵を使う
- sshpassを使う
expect -c 'spawn ssh userName@serverName; expect "assword:"; send "myPassword\r"; interact'
- -c:スクリプトとして以下の分を実行する
- spawn:コマンドを実行、今回はssh
- expect:名前が紛らわしいのですが、これで入力待ち。次の分が正規表現で見つかるまでまつ。"assword:"だと、Password:とpassword:両方に対応。サーバーによってこの文字が違うかもしれないので注意
- send:キー入力、今回はパスワード
- interact:シェルに戻る
- シングルクォーテーションとエスケープ:今回は、シングルクォーテーションで全体を囲み、文字列をダブルクォーテーションで囲みましたが、ダブルクォーテーションで始めると、スクリプト中の文字列はエスケープして「\"」を使う必要あり。見辛いので前者をオススメ。

2020年5月2日土曜日
Excel VBA ~ ClassをDictionaryに格納するコツ Dictionaryの癖…オブジェクトは参照渡しになってしまう、Watch式に入れるとEmpty Itemができてしまう…
Dim setArray, dics As New Dictionary, c As Integer ReDim setArray(maxNum - 1) Do While Not IsEmpty(setSheet.Cells(r, 1)) Set setArray(c) = New myClass dics.add setSheet.Cells(r, 1).Value, setArray(c) c = c + 1 r = r + 1 Loop
Set units = New Dictionary units.RemoveAll
- DictionaryにObjectを格納すると、強制的に参照渡しとなる Object in the Dictionary forces to be reference
- よって、同名・単一クラスをDictionaryに格納することはできない Therefore, the same name / single class cannot be stored in Dictionary
- 同名オブジェクトを流用する際は、値が残る場合があるので、RemoveAll等で強制クリアする When diverting an object with the same name, the value may remain, so forcibly clear it with RemoveAll etc.
- ウォッチ式にDictionaryを入れるとEmptyデータができてしまうので注意する A dictionary to the watch expression, empty data will be created.
2020年1月26日日曜日
Ubuntu 19.10 日本語 Remixを外付けHDDにインストールする手順(18.04 + Universal-USB-Installerで失敗した後)
外部USB HDD or SSD or メモリにインストールして、差した時だけ
Ubuntuが起動する形がいいと思います。
パーテーション切ったりは怖いですからね。
シェルのみであれば、Windows10上で、WSL+Ubuntuでもイケます。
【SPEC】
- PC : NEC Lavie LL850/S
- HDD : Buffalo MiniStation 500GB
- Live USB作成ツール : Rufus-3.8
- Ubuntu本体ISO : ubuntu-ja-19.10-desktop-amd64.iso
【手順】
(1) Live USBメモリの作成
※これはお試し用で、データや設定の保存はできません!!最初にUbuntu 18.04とUniversal-USB-Installerで試しましたが、
Mounting /cow on root failed: Invalid argument overlay mount failed
- 19.10を使う→リンク
- Rufusで作成する際、Persistent partition Sizeを適当(半分くらい)な値にする
(2) 内蔵ストレージの取り外し
※これを行わないと、内蔵ストレージにUbuntuがインストールされてしまいます!!(3)の本番インストールの際、内蔵ストレージが存在すると、外部USBドライブを指定できません。物理的に取り外す必要があります。繋いだドライブを全て選択できたらよかったのにな…。
(3) Live USBとインストール用HDDを接続し、起動
パソコンの起動時にF2キー(NECノートPCの場合)を押し続け、BIOS設定画面を開きます。Boot関係のタブにて、USB MemoryとUSB Strageの順位を内蔵HDDより上位に設定します。これでUSBに起動可能ドライブを差している時は、そちらを優先して起動するようになります。(4) Ubuntuをインストール
デスクトップに「Ubuntuをインストール」アイコンがあるので、そこからインストールします。昔と比べて分かりやすいGUIでインストールできます。
日本語設定をしたにもかかわらず、半角/全角キーで日本語切り替えができない場合、キーボードレイアウトが英語になっている可能性があります。
端末から、下記コマンドで日本語レイアウトに変更できます。
setxkbmap -layout jp
2019年12月15日日曜日
Alteryxでフォルダ作成 mkdir するのに R tool を使う
ということで、R Toolを使ってAlteryx内でDynamicにフォルダ作成する方法を紹介します。
Alteryxワークフロー

フォルダ指定とディレクトリツール
フォルダ指定のダイアログを出して、結果をディレクトリツールに渡し、フォルダ内の*.csvファイルを開きますBlock Untilツール
Rでフォルダを作るのを先に完了させるため、実行順を強制的にしていします。Alteryxは並列処理するので、場合によっては「フォルダが無いよ!」エラーが出てしまうので。フォルダ作成、フィールド付加 Append Field
Rツールでフォルダを作成し(コードは後述)、そのフォルダ名をFieldとして付加、それと元のファイル名で保存パスを作成します。最後のOutputでは、ファイル名をダミーにしておいて、

フルパスを変更 Change FullPath を選ぶことで、保存フォルダとファイル名を自由に設定できます。元のファイル名を使ったり、日付を入れたり、Excelファイルの場合はファイル名+「|||シート名」でシート名を指定したり。

Rコード
df<-read.Alteryx("#1", mode="data.frame") mkdir<-paste(df[1,1], "output", sep="") dir.create(mkdir) names(mkdir)<-c("outputFolder") write.Alteryx(mkdir, 1)
df[1,1]は1行目1列目のデータ、この場合はグループ化した選択フォルダとなります。作りたいフォルダとして、今回はそのフォルダに"output"を付加しました。Rの文字列結合はpasteを使いますが、sep=""を指定しないとスペースが入るので注意します。
dir.create()でフォルダを作成します。元々存在する場合は警告がでるかも。
names()<-c("itemname")で項目名を指定します。指定しないと、長々とした自動項目名となり、テーブルによって変わってしまうので不便です。これをwrite.Alteryxで出力し、前述したOutput Fileのパスとして利用します。
まとめ
ここまでくるとハッと思いつきますね、「これならRで全部やればいいんじゃない?」その通りだと思います。ちなみに、Alteryxはcommand実行ライセンスが別売りなので、自動実行したい時は別料金。
高額なライセンス料と見合う売り上げが見込めないなら、R勉強した方がいいんじゃない?コミュニティも英語ばかりだし、コードや英語にアレルギーがある人には無理なツールです。導入は慎重に!
2019年11月30日土曜日
Excel VBAでグラフの範囲をグラフタイトル+複数列(配列)で設定する
今回は、バラバラに並んだ項目名から、そのグラフに必要な列を検索し、グラフの範囲指定を自動化します。
実務では、Alteryxでビッグデータから作った表の項目が、毎回違う場合でも、同じフォーマットに出力するために作りました。やっぱりまだExcelのグラフの方がフレキシブルで綺麗なので。
こんな表から、
定型フォーマットのグラフ一覧へ、データをセットするコードです。
ユーザー定義クラス graphInSheet
Public graphSet As Dictionary Private targetSheet As Worksheet Public Function setSheet(mySheet As Worksheet) Set targetSheet = mySheet With targetSheet Set graphSet = New Dictionary Dim chart For Each chart In targetSheet.ChartObjects graphSet.Add chart.chart.ChartTitle.Text, chart.Name Next End With End Function Public Function setSourceData(GraphTitle, setRange As Range) With targetSheet Dim currentChart As chart Set currentChart = .ChartObjects(graphSet(GraphTitle)).chart currentChart.setSourceData Source:=setRange End With End Function Public Function setCategoryMinMax(GraphTitle, MinScale, MaxScale) With targetSheet Dim currentChart As chart Set currentChart = .ChartObjects(graphSet(GraphTitle)).chart currentChart.Axes(xlCategory).MinimumScale = MinScale currentChart.Axes(xlCategory).MaximumScale = MaxScale End With End Function
メインコード「RangeをUnionする」
Public Sub setDataToGraph() Dim payment, payments payments = Array("現金", "カード", "PayPay") '今回はグラフとデータを別にしましたが、同じシートでも可 Dim graphs As New graphInSheet graphs.setSheet ThisWorkbook.Worksheets("graph") Dim dataSheet As Worksheet Set dataSheet = ThisWorkbook.Worksheets("data") Dim region For Each region In graphs.graphSet Dim dataColumns As New Dictionary Dim setRange As Range, lastRow With dataSheet '横軸(項目に対して固定)を設定 lastRow = .Cells(.Rows.Count, 1).End(xlUp).Row Set setRange = .Range(.Cells(1, 1), .Cells(lastRow, 1)) '各グラフに必要な項目の列を収集 dataColumns.RemoveAll For Each payment In payments dataColumns.Add .Rows(1).Find(region & "_" & payment).Column, Null Next '列からRangeの集合を作成し、グラフにセット Dim setColumn For Each setColumn In dataColumns Set setRange = Union(setRange, .Range(.Cells(1, setColumn), _ .Cells(lastRow, setColumn))) Next End With graphs.setSourceData region, setRange Next End Sub
一番左の横軸となる列を範囲指定し、そのRangeへUnionで必要な列を追加していきます。できあがったRangeをChartObjectにsetSourceDataで入れればいいのですが、グラフのタイトルでなく、「Chart12」などとExcelで決められたオブジェクト名で指定するのが不便なため、ユーザー定義クラスでシート中の全グラフを保持しておきます。
ただし、グラフタイトルが被るとうまく動作しませんので、別の方法を考えなければいけません(結局Chart番号??)。
2019年11月24日日曜日
AmazonのブラックフライデーでSSDを購入してHDDから換装→爆速でビックリ
爆速で届いて、ちょっとクローンに躓きましたが、半日で換装完了。これはオススメ…というか、今までハードディスクがボトルネックだったのね!
【PC】 NEC LaVie LL850/S
【HDD】 HGST SATA 6Gb/s 5400rpm 1.5TB
↓
【SSD】 シリコンパワー SSD 512GB 3D NAND採用 SATA3 6Gb/s

シリコンパワー SSD 512GB 3D NAND採用 SATA3 6Gb/s 2.5インチ 7mm PS4動作確認済 3年保証 A55シリーズ SP512GBSS3A55S25
→これが、ブラックフライデーで 5,870円まで下がっていました。
必要なものは他に、スペーサーとUSB-SATA変換ケーブルだけです。ソフトは無料のもので十分。

KAUMO 2.5インチ SSD/HDD用スペーサー 7mmを9.5mm厚に変換 耐熱シール付き KM-296

SATA-USB 3.0 変換ケーブル YOKELLMUX 2.5インチ SSD/HDD用
マシンやSSDによって換装のコツは色々あるようですが、私の場合は
GPTでフォーマット → クローン
でうまくいきました。ソフトはEaseUS Todo Backup(無料版)です。
(有料版もありますが、クローンは無料版でできます)
クローン作製時、ハードディスク全体と、ドライブそれぞれのチェックが可能ですが、最初にC(Windows)ドライブのみのクローンを行うと、交換後にBIOS画面から進まずに失敗。「システムリカバリ」など無駄と思われる領域があっても、全体のクローンを作るべし(詳しい方は選択して適切なパーティションを切ってください)。
全体のクローンは1時間ほどかかりました。そのまま寝てしまったので半日かかったことになりますが、実際は準備も含め2時間ほどでしょう。
クローンが出来たら、HDDからSSDに換装して起動するだけです。スペーサーはロゴマーク側、隠れて見えなくなる方です。





交換後は、今までのモッサリは何だったのだろう?という軽さ。そしてハードディスクが無くなって気付く静かさ。耐久性はこれから見ていきますが、これだけ快適なら次もSSDでしょう。もうカリカリ音には戻れません。NAS用も普及価格に落ちてきてくれないかな…。
2019年10月25日金曜日
PowershellからAccess VBAのサブプロシージャを実行する(ついでに最適化を行う)方法
Hiddenな動作、例えばExcelで別名ファイルを生成したり、AccessでCSV読み込みとテーブル作成クエリを実行したい場合、元ファイルを開くことなく、Powershellの実行だけで完了するので、自動化の目途が立ちます。
今回はAccessの例を紹介しますが、Excelの場合も殆ど同じですので、試してみてください。
2019年9月21日土曜日
光コラボ乗り換え~AsahiNet光から楽天ひかりへ
今までの自宅のネット回線は、
①フレッツ光+Biglobe(プロバイダが遅い)
②フレッツ光+Asahiネット(高い)
③Asahiネット光(障害多い)
といった経歴で、光コラボは事業者変更時にフレッツ光解約を伴うため、手数料や手間がかかることがあり、③を我慢して使っていました。しかし2019年7月から、光コラボの事業者変更が工事無しで簡単にできるようになったと知り、すぐに次の業者を探しました。
光コラボ業者の選定
値段的にはSo-netか楽天。ただしSo-netは最初だけ安い遣り口です。楽天は特典が楽天ポイントなので、楽天市場を良く利用する人には良。ということで楽天ひかりに決めました。
3年縛りのキャンペーン特典↓
- Archer C6プレゼント
- 楽天ポイント 7000ptプレゼント
- 工事費無料
乗り換え手数料は軽く吹き飛びます。デメリットは、プロバイダが原因でネットが遅すぎる場合に、違約金を払わなければ辞められないことですが、使えないくらい遅ければクレーマーとなって戦えばいいと思います。
月額料金は、
- 4,800円(税込5,184円)
- 特典200ポイント+楽天カード払い1%=48ポイント
つまり、実質4,936円。AsahiNet光は5,486円(長期割引100円含む)なので、月550円安くなることに。選ばない手はありません。
楽天ひかりを契約する場合は、楽天会員かつ楽天カードを持っている方がお得です。


光コラボの事業者変更~申し込み方法
事業者変更手続きは、スマホのMNPに似ています。まず、変更元のAsahiNet光から、「事業者変更承諾番号」を貰います(会員ページから)。取得は無料ですが、変更が完了すると手数料2,000円が発生します。
日中に手続きを行えば、その日のうちに番号がメールで届きます。それを変更先の楽天ひかり申込みホームページで入力するのです。
楽天ひかりのホームページから、「他社の光コラボから乗り換え」を選択、戸建てかマンションを選びます。事業者変更承諾番号は変更元からメールで届く、Fで始まる番号です。番号の有効期限は15日なので、すぐに手続きしましょう。西日本の方はCAF番号も必要なようです。
迷うのは、近隣の電話番号を使った仮番号の入力。フレッツ光の収容先の目安にするのでしょう。近くのお店の電話番号でいいのですが、県や市区町村境をまたがないように。間違ったとしても多少手続きが遅れるくらいだと思いますが。
光コラボの事業者変更~設定方法
申し込み翌日に電話があり、本人確認の後、
- 約2週間後の開通
- 工事は発生しない
- 夕方には開通するので、そのタイミングで機器設定して下さい
と説明を受けました。フレッツ光回線をそのまま使うので、収容先を変えるだけで事業者変更ができるのです。その後、アカウントのお知らせが郵送されてきます。

切り替えの次の日、まだAsahiNet光のアカウントで繋がっています。ルーターの設定画面で、楽天ひかりのアカウント設定をします。恐らく設定後に、旧プロバイダには繋がらなくなると思われます。インターネット接続タイプは「PPPoE」になっていると思いますので、そのままで。ユーザー名とパスワードを新しいものに書き換えます。早速スピードテスト↓

早い!!!早朝でしたが、AsahiNet光はどの時間帯も3桁に達したことはなかったので。
楽天ブロードバンドメンバーステーションでポイントキャンペーンなど設定
楽天ブロードバンドメンバーステーションから、
- 楽天スーパーポイント口座情報変更
- 楽天スーパーポイント口座番号の表示手続き(楽天会員アカウントで)
これで、楽天ブロードバンドと楽天会員アカウントが紐づきます。
(というか、最初から紐づけてくれたらいいのに…)
これを行わないと、楽天ポイントが貰えないので注意!
ネットは爆速になり、月額料金は安くなる。簡単手続きで乗り換えできるので、今の光コラボに満足していない方は切り替えをおすすめします。ただし、手数料や解約金が大きくなることもあるので、何度も切り替えることのないよう、ご注意あれ。
2019年8月9日金曜日
Alteryx : R Toolでテーブルを横展開する(reshape wide)~Cross Tabツールを不便に思ったら~
縦に並んだテーブルを、ある項目をキーとして横方向に展開するには、Cross Tabツールを使います。
しかし、このツールには制限があり、展開する列は1つのみで、列名を自動付与することができません。そのため、2つ以上の列を横展開するには、Cross Tabを複数個用意してからSelectツールで列名を変更してから結合するという、バカらしくも面倒なフローが必要となります。そこで、それらの処理をR Tool一発でできるようなコードを書きました。
困ったときはR Tool、R言語を覚えつつ、最終的にAlteryxはイラナイ!となるのが、コスト・スキル的にベストだと思います。
処理の概要とワークフロー
例として、店舗名と商品ID、Key Performance Indicatorがいくつかまとまった表をソースとして、グラフの描画に使うため、日付ごとに全て横並びにしたい場合。↓
下図ワークフローの、Cross Tabを使う流れの場合、ShopとItemIdを文字列結合してキーとし、Group byにDateId、ヘッダーにShopItemId、値にKPI_1を指定します。値に指定できるのはひとつだけなので、KPI_2はもう一つのCross Tabで処理し、Joinしなければなりません。
しかも、Cross Tab後のデータはKPI_1かKPI_2か項目名では分からなくなるので、それぞれ項目名をリネームする必要があります。私が担当を任された表では、これが10以上あったので、超絶面倒になって、R言語を勉強した方がマシ!と思った次第です。
そもそもAlteryxのグラフツールが、項目を抽出して項目名を付けてくれるとか、横軸のインターバル(間引きして見やすく)とかが柔軟にできていたら、この横展開も必要なかったのに…。結局Excelのグラフを使い、参照するテーブルを更新する形にしました。

R Toolの処理解説
--------------------------------------------------------------------------------------
df <- read.Alteryx("#1", mode="data.frame")
sidf <- subset(df, select=c(Shop, ItemId))
ShopItemId <- apply(sidf, 1, paste, collapse = "_")
df <- cbind(df, ShopItemId)
df <- df[ , colnames(df)!="Shop"]
df <- df[ , colnames(df)!="ItemId"]
df <- reshape(df, timevar="ShopItemId", idvar="DateId", direction="wide")
write.Alteryx(df, 1)
--------------------------------------------------------------------------------------
上から説明します。
--------------------------------------------------------------------------------------
