アナログCPU:5108843109

ゲームと音楽とプログラミング(酒と女とロックンロールのノリで)

('ω') < イザユケエンジニャー

自作アドインの作り方

たまに一部忘れるので自分のためにもメモ。
Excelでの作業が多いなら、作り方使い方を覚えると非常に便利です。

そもそもアドインとは?

ひとことで言うと「拡張機能」です。

普通にマクロを作るとそのブックでのみ有効ですが、
アドイン化することで、新規ブックだろうが既存ブックだろうが、まるでExcelの機能のように使えます。

今回はそれを自作する方法の話ですが、
便利アドインがフリー配布されていたりしますので、そういうものを導入するだけでもよいかもしれません。

続きを読む

シートをコピーして名前を変更するプロシージャ

サンプルには記載していませんが、
シート操作はエラーが起きやすいので、必要に応じてエラー処理が必要になります。

左からA,B,Cとシートが並んでいるとき
コピー元としてシートB、コピーしたシートに付ける名前として「D」を引数にして
このサンプルを実行すると、A,D,B,C という並びになります。

'*
'* シートをコピーする
'*
'* in  wsBaseSheet   コピー元ワークシート
'*     sNewSheetName コピー後のシート名
'*
Private Sub SheetCopy(ByVal wsBaseSheet As Worksheet, ByVal sNewSheetName As String)

    Dim lFmtIndex As Long
    Dim lNewIndex As Long
    
    'シートをコピーして、コピー元の手前に置く
    wsBaseSheet.Copy Before:=wsBaseSheet
    
    'コピー元シートのインデックスを取得する
    lFmtIndex = Sheets(”コピー元シート名”).Index
    'コピー先のインデックスは「コピー元 - 1」
    lNewIndex = lFmtIndex - 1
    
    'コピー先シートの名前を変更する
    ThisWorkbook.Sheets(lNewIndex).Name = sNewSheetName

End Sub

ざっくりSQL入門 #11:トランザクション

MySQLを前提に書いています。一部関数などは方言差がある場合もあるのでご注意ください。

今回はトランザクションについて。


トランザクションとは

「分けることのできない複数の処理をまとめた単位」です。
(データベースに限った意味合いではありませんが、以降、データベースについての話とします)

例えばどういうこと?

ひとつの処理に対して、複数のテーブルに対する更新が発生する場合があります。
例えば通販サイトの購入手続き時…

注文のメイン情報であるorderテーブル(order_id, user_id, name, address, ...)と
orderに紐づき、購入商品単位のデータをもつorder_productテーブル(order_id, product_id, count, price, ...)
の2つがあるとします。

注文が発生すると、それぞれのテーブルにINSERTが発生することになります。

order

order_id user_id name address ...
51088 43109 鈴木太郎 東京都新宿区... ...

order_product

order_id product_id count price ...
51088 101 2 2000 ...
51088 102 5 5000 ...

このとき、orderへのINSERTは成功し、order_productへのINSERTは失敗してしまうと、
orderにだけ中途半端なデータが残ってしまうことになります。

それでは困る、というときに、この2つのINSERTをまとめてひとつのトランザクションにするのです。

具体的にはどう書くの?

トランザクションの開始時に「BEGIN(もしくは START TRANSACTION)」
トランザクションの正常終了時に「COMMIT」
トランザクションを全部取り消したいときに「ROLLBACK」です。
COMMITを書いていない場合や途中でエラーになった場合は、
ROLLBACKを明示しなくとも全部取り消されます。

BEGIN;
INSERT INTO `order` VALUES ...
INSERT INTO `order_product` VALUES ...
COMMIT;

SQLを手打ちするだけならROLLBACKを使うことはそうそうないのですが、
アプリケーションで実装する場合は例えば以下のようなパターンが実現できます。

// UPDATEを行うが、
// その結果が1件以下ならそのUPDATEを取り消し、
// 2件以上なら別のテーブルにもINSERTを行う

BEGIN;

UPDATE `hoge` SET ... ;

if ( /* UPDATEの結果が1件以下 */ )
{
    ROLLBACK;
}
else
{
    INSERT `fuga` ... ;

    COMMIT;
}

暗黙的なコミットについて

「TRUNCATE TABLE」など一部の構文については、コミットが発生してしまうため注意が必要です。
過去に詳しく書いていますのでリンクにとどめておきます。
トランザクションの挙動検証 - アナログCPU:5108843109

プレースホルダのいい感じの作り方

頭が悪いタイトル。

例えば以下のようなクエリを組み立てることはよくあるのですが

SELECT ...
FROM ...
WHERE `id` IN (1, 2, 3, ...)

ここ。

IN (1, 2, 3, ...)

ここをPHP上で組み立てるのに最初は苦労しましたが、今は以下のように書いています。

$param_list = array(1, 2, 3, ...);

$query  = "SELECT ... ";
$query .= "FROM ... ";
$query .= "WHERE `id` IN (" . implode(",", array_fill(0, count($param_list), "?")) . ") ";

理屈は以下のとおり。

  • $param_listの要素個数分の配列を生成し、中身は「?」にする
  • implodeを用いてカンマ区切りの文字列に変換する

PHPは配列まわりの関数を使いこなすとこうやってあっさり1行で済むのが楽しいところですね。


ただ、毎回コピペしてるけどもうちょっとスマートにしたいな。

ざっくりSQL入門 #10:一時テーブルを活用する

MySQLを前提に書いています。一部関数などは方言差がある場合もあるのでご注意ください。

今回は一時テーブルについて。

一時テーブルとは、普段使用しているテーブルとは異なり、その名の通り、一時的に保持されるテーブルです。
作成した一時テーブルはそのセッションでのみ使用可能で、セッションが閉じられるときに自動で削除されます。
複数のセッションが同時に同じ名前の一時テーブルをそれぞれで作成・使用することができます。

基本的な構文

以下の書き方で、結果セットを簡単に一時テーブル化することができます。

CREATE TEMPORARY TABLE 【一時テーブル名】
SELECT ...

このテーブルはセッション終了時に削除されますが、個人的には明示的に削除するのが好きです。

DROP TEMPORARY TABLE IF EXISTS 【一時テーブル名】

活用例

普通は一時テーブルを用いることなく対応可能でしょうが、
一時テーブルを活用することで、可読性や実行速度などが大幅に向上する場合があります。

(個人的に)ありがちな例を以下に記載します。

  • 複雑な集計を行い、その結果に対してさらに処理を加えたい場合
    • 何らかのスコア計算を行い、それに順位を付けたい、など
  • あるレコード群に対して、段階的に処理を加えたい場合
    • Aに該当するレコードにaの処理を加え、それ以外でBに該当するレコードにbの処理を加え…
  • 大規模なINSERTレコードを生成する場合
    • いくつかの複雑な条件を用いて一時テーブル上にINSERTしたいレコード群を構築していき、最後に一括でINSERTする

ざっくりSQL入門 #9:よく使う関数

MySQLを前提に書いています。一部関数などは方言差がある場合もあるのでご注意ください。

今回は、(個人的に)よく使う関数を記載しておきます。
ただし集計関数についてはこちら

続きを読む

ざっくりSQL入門 #8:クエリを書く<データの削除編>

MySQLを前提に書いています。一部関数などは方言差がある場合もあるのでご注意ください。

今回は、DELETEやTRUNCATEの構文を用いて、レコードの削除を行う方法について。


DELETEとは

指定したレコードを削除します。
指定方法はおなじみWHERE句。

DELETE FROM 【テーブル名】
WHERE       【条件】

WHERE句の条件に合うレコードがすべて削除されますし、
WHERE句を省略すると全件削除されるため、実行前にはくれぐれも注意してください。

TRUNCATEとは

指定したテーブルを空にします。

TRUNCATE TABLE 【テーブル名】

これだけ。
空にするということはつまり全件削除されるため、
こちらも実行前にはくれぐれも注意してください。

全件削除するときはどちらがいいの?

前述のとおり、DELETEもWHERE句を省略すればテーブルが空になります。
TRUNCATEとどちらを用いるべきかは、
以下の違いを参照の上、適した方を選ぶことになります。

TRUNCATE DELETE
速度 高速 低速
auto_increment 初期化される 変わらない
トランザクション ロールバック不可(暗黙のコミット) ロールバックできる

少なくとも、「auto_incrementを維持したい」「トランザクション内で実行する」という場合は
DELETEを選ぶ必要があるというわけです。
トランザクションについては後から説明しています

これらの差異は、
TRUNCATEは内部的に「テーブルを一度削除して同じ構造の空テーブルを作る」という処理で、
DELETEはあくまで「レコードを削除する」という処理、という根本的な違いから来ています。

削除対象がどれだけあろうとテーブルを作り直すだけのTRUNCATEは高速ですが、
新しいテーブルなのでauto_incrementもリセットされますし、
消えるレコードの中身を見ることもないので復元ができない…ということです。

ざっくりSQL入門 #7:クエリを書く<INSERT&UPDATE編>

MySQLを前提に書いています。一部関数などは方言差がある場合もあるのでご注意ください。

今回は、INSERTやUPDATEの構文を用いて、レコードの追加や更新を行う方法について。


INSERT・UPDATEとは?

新しくレコードを追加するときは「INSERT」、
既存レコードを更新するときは「UPDATE」を用います。
新しくレコードを追加したいが既存の場合は上書きしたい(もしくは何もしない)、という場合は
INSERTのオプションで対応します。

続きを読む

ざっくりSQL入門 #6:クエリを書く<サブクエリ&UNION編>

MySQLを前提に書いています。一部関数などは方言差がある場合もあるのでご注意ください。

今回は、サブクエリやUNIONを用いて、複数のクエリの結果を組み合わせる方法について。


サブクエリとUNION、その違いについて

サブクエリは「あるSELECTクエリをテーブルや値とみなして扱う」方法、
UNIONは「複数のSELECTクエリの結果セットを足し合わせる」方法です。

続きを読む

FE聖戦:ネタバレを避けたかんたん攻略メモ(後半)

ネタバレは見たくないけど手に入るアイテムなどを把握しておきたかった自分用メモ、後半戦。
前半に比べると「重要アイテムだけどなかなか気づかない条件」は少なそうだけども。

前半はこちら
FE聖戦:ネタバレを避けたかんたん攻略メモ(前半) - アナログCPU:5108843109

手に入るアイテムメモ

  • 6章
    • リライブの杖(ラナ→ユリア 会話)
    • スキルリング(ヨハン隊右側の村)
    • オーラもしくはリザイア(ユリア→セリス 会話)
      • ソファラ城制圧後~イザーク城制圧前ならオーラ、イザーク城制圧後ならリザイア
      • オーラの場合は前半のものが引き継がれる模様?
    • ゆうしゃのおの(シュミットを倒す)
      • 前半でレックスが入手したものが引き継がれる
    • 【未継承の場合】リターンリング(ハロルドを倒す)
    • 【未継承の場合】スピードリング(ヨハンを倒す)
    • 【未継承の場合】エリートリング(ヨハルヴァを倒す)
    • 【未継承の場合】とうぞくの剣(ダナンを倒す)
  • 7章
    • ゆうしゃの剣(パティ→セリス 会話)
    • トローン(イシュトーを倒す)
    • スピードリング(レンスター城南東の村)
    • シールドリング(ダーナ城西の村)
    • バリアの剣(レイリアでレンスター城に一番近い村)
    • 【未継承の場合】ねぎりのうでわ(クトゥーゾフを倒す)
    • 【未継承の場合】スキルリング(ジャバローを倒す)
    • 【未継承の場合】マジックリング(ライザを倒す)
    • 【未継承の場合】ナイトキラー(ブラムセルを倒す)
    • 【未継承の場合】ぎんの大剣(ブルームを倒す)
  • 8章
    • パワーリング(一番北の村)
    • シーフのうでわ(一番南東の村)
    • 【未継承の場合】ゆうしゃのやり(ムハマドを倒す)
    • 【未継承の場合】シールドリング(オーヴォを倒す)
    • 【未継承の場合】ゆうしゃのゆみ(コノート城西のジェネラルを倒す)
    • 【未継承の場合】ゆうしゃの剣(コルータを倒す)
    • 【未継承の場合】いのりの剣(たいちょうを倒す)
    • 【未継承の場合】キラーボウ(マイコフを倒す)
  • 9章
    • バリアリング(左側中央の村)
    • トルネード(ムーサーを倒す)
    • いのりのうでわ(アリオーンを倒す)
    • バサークの杖(ハンニバル・シャルロー 会話)
      • グルティア城制圧後、シャルローがハンニバルの隣に待機
    • 【未継承の場合】リターンリング(ディスラーを倒す)
    • 【未継承の場合】パワーリング(トラバントを倒す)
    • 【未継承の場合】リザーブの杖(カパトギア軍ハイプリーストを倒す)
  • 10章
    • ライブのうでわ(セリスでアルヴィスを倒してから、以下いずれかに待機)
      • シアルフィ城の東にある岬の先
      • シアルフィ城南西の砂浜
    • ティルフィング(セリス・パルマーク 会話)
    • マジックリング(左下の村)
    • ボルガノンヒルダを倒す)
  • 終章
    • ナーガ(ユリアがヴェルトマー城に入城)