ゆるおたノート

Tomorrow is another day.

【VBA】クラスの作り方を整理してみた(基本用語編)

前回の記事が長すぎたので、良きところで分割してみました。

【VBA】クラスの作り方を整理してみた(移行手順編) - ゆるおたノート

クラス

意味

今回のメイン。
「Aというオブジェクトは、BプロパティやCメソッドを持っている」といったオブジェクトの定義を行う。
本やWebページでは、「設計書」や「鋳型」と説明されていることが多い。

VBAでは、クラスモジュールを使ってユーザー自身が新しいクラスを作成できる。

インスタンス

実際にクラスを利用する時は、下記どちらかの段階でNewキーワード*1を使って「クラス(=設計図)からオブジェクト(=実体)を生成」する。

この生成されたオブジェクトのことをインスタンスと呼ぶ。

モジュール

処理の集まり。
VBAでは、標準モジュールクラスモジュールシートモジュール等がある。

今回は「クラスモジュール」にクラスの設計を記入していく。

スコープ

データを参照可能な範囲。「●●の中ならアクセスOK」の●●の部分。
プライベートとか、パブリックとか、グローバルとかを使って、「~~レベル」と呼ばれる。

過去記事に、掲載当時に私が理解していた範囲でまとめています。

プロパティ

インスタンスの内容や状態に関する情報*2。多くは「属性」と訳される。
VBAでは、ブックの名前やセルの値、場所、オブジェクトの参照値、など。

情報をインスタンス自身に持たせて、「●●の値を取得する」という時や「値を設定する」といった時に使う。
スコープをPublicにすることで、外のモジュールからインスタンス.プロパティ名で呼び出せるようになる。

プロシージャで定義する場合、使用するプロシージャは機能別にGetLet/Setの3種類に分かれている。

名前は「大文字始まり」の名詞が多い(気がする)。

値を取得する

Property Getプロシージャ

プロパティの値を返すことのみ出来る。
VBAの仕様上、Property Getプロシージャ内で直接「プロパティへの代入・設定」することはできないので、「変数や定数を経由」して値を設定する必要がある。

使用例
'[クラスモジュール] Exampleクラス
Private 仮変数 AsProperty Get プロパティ名()As 型
    仮変数 = 123
    プロパティ名 = 仮変数
End Sub
'[標準モジュール]
Sub test()
    Dim ex As New Example
    'インスタンスexのプロパティの中身を確認
    Debug.Print ex.プロパティ名 '「123」と表示される
End Sub

値を代入する

Property Letプロシージャ

プロパティに値を設定するためのプロシージャ。
値を代入するときのLetキーワード*3が入っている。

使用例
'[クラスモジュール] Exampleクラス
Private 仮変数 AsProperty Let プロパティ名(仮引数 As)
    仮変数 = 仮引数
End Sub
'[標準モジュール]
Sub test()
    Dim ex As New Example
    ex.プロパティ名 = 123 'プロパティに値を代入
End Sub
Property Setプロシージャ

参照するオブジェクトをプロパティに設定するためのプロシージャ。
Subプロシージャ等でオブジェクトを代入するときのSetと同じ。

使用例
'[クラスモジュール] Exampleクラス
Private 仮変数 As オブジェクト系の型

Property Set プロパティ名(仮引数 As オブジェクト系の型)
    Set 仮変数 = 仮引数
End Sub
'[標準モジュール]
Sub test()
    Dim ex As New Example
     'プロパティにオブジェクトの参照値を代入
    Set ex.プロパティ名 = オブジェクト
End Sub

引数の正しい使い方?

リファレンスによると、同じ名前のプロパティプロシージャは、引数名とデータ型をほぼ同じにしなければならないらしい。

The first argument through the next to last argument (1, …, n) must share the same names and data types in all property procedures with the same name.

プロパティ プロシージャ (VBA) を作成する | Microsoft Docs

同じ名前のPropertyプロシージャ間では、最初の引数~最後から2番目の引数は、同じ引数名とデータ型を共有していなければならない。

ただ、そうなっているクラスをあまり見たことがない気が。
…初心者の私が知っている限りでは。

「実際はどちらでも良い(ことにしてある)」ってことなのかな…?

<2019/10/15追記>
前回記事のコメントにて、imihito(id:imihito)さんより下記補足いただきました。 ありがとうございます!

VBAでも常に守られています(条件を満たさないPropertyを作成するとコンパイルエラーになります)。

Property Getの返り値は、Property Set/Letの最後の引数と同じ型にする必要がありますし、
Property Getの引数は、Property Set/Letの最後から1個前の引数までと、名前・型が一致する必要があります(Getに引数が無ければ、Set/Letの引数はGetの返り値と同じ型の1個のみ)

前回の記事のコメント欄より

個人的には、最後の1文が重要そうです!

メソッド

命令。
SubプロシージャFunctionプロシージャが使える。

名前は「大文字始まり」で、「●●する」のように動詞にすることが多い(気がする)。

スコープをPublicにすることで、外のモジュールからインスタンス.メソッド名で呼び出せるようになる。

'[クラスモジュール(Exampleクラス)]
Sub メソッド名(仮引数 As)
    '処理
End Sub
'[標準モジュール]
Sub 使用例()
    Dim ex As New Example
    ex.メソッド名 引数 'メソッドの呼び出し
End Sub

引数を「省略可」にするには…?

VBAでは、引数の初期値には定数(もしくは定数式)しか指定できない
ということは、Optionalな引数にプロパティの値を指定したい時は一工夫が必要そう…(調べ中)

いま頭にあるのは、下記の2つ。

  • プロパティ用の値を変数ではなくモジュールレベルの定数で定義する
  • プロシージャの中で引数の有無を判定して値を設定する
    → 数値だと初期値が0なので少し面倒かも…

あとがき

ついつい適当な憶測で書いてしまうので、記事をアップする時はこんな弱小ブログでも変な認識・知識を広めちゃったりしないか毎回結構ドキドキです…

でも、今回VBAブロガーの方々に色々ご指摘いただけて嬉しいです。とっても勉強になります!
私の頭で全部理解できてるかと言ったら微妙ですが、精進します!!

…自分でも、もっとよく調べてから書かないとですね。

このシリーズについて

初心者の頭でVBAでクラスを作成する方法の整理に挑戦しています。

連載目次

  1. オブジェクト指向って、なんだ? - ゆるおたノート
  2. 【VBA】クラスの作り方を整理してみた(移行手順編) - ゆるおたノート
  3. 当記事【VBA】クラスの作り方を整理してみた(基本用語編) - ゆるおたノート

注釈

*1:<2019/10/14追記>
当初「Newステートメント」と書いていましたが、「Newキーワード」の誤りでした。誤解を招く表現、大変失礼いたしました…

▼参考

そして、ご指摘頂いたチン☆テクラ(id:akashi_keirin)さん・鵜原パソコンソフト研究所さん、ありがとうございます!

*2:テレビゲームで言うところの火属性とか、ステータス異常とか、能力値とか。

*3:本来は変数などに代入する時も必要だけど、普段は省略しても動くように作られているらしい。

【VBA】クラスの作り方を整理してみた(移行手順編)

標準モジュールに書いていた処理を、何とかクラスモジュールに移行出来るようになってきました。

まだ世界がごちゃごちゃですが、記憶の新しいうちにメモを残してみます。

基本用語・概念については、こちらからどうぞ。 【VBA】クラスの作り方を整理してみた(基本用語編) - ゆるおたノート

手順

手続きの流れを考える

処理のテーマ

今回は、例として「フォルダ内の複数のブックで、シートの値を置き換えて名前を変えて保存する」場合を考える。

[例]手続きの流れ

だいたいこんな処理を書くと思う。(日本語でごめんなさい)


  • フォルダ内に処理対象のブックがあるか確認する
  • 拡張子付きファイル名を取得
  • パスを取得
  • パスを指定してブックを開く
  • シートを取得
  • テーブルを取得
  • セルの値を取得
  • 文字列に変換
  • 文字列を置き換える
  • ブックの拡張子付きファイル名を取得
  • 現在のファイル名から新しいファイル名を取得
  • 格納先のフォルダを取得
  • ファイル名とフォルダの場所からフルパスを取得
  • 新しいパスでブックを保存する
  • ここまでの処理を同じフォルダのブックの数だけ繰り返す
  • メッセージボックスで「完了」をお知らせ。

処理の分解

処理を区切ってプロシージャを分ける

「〜して、〜して、〜して、…」のように、「『〜して』毎」*1に1つのプロシージャにしてみる。
これを、一般に部品化と呼ぶ。

※詳しくはこちらが参考になります*2 VBA 中級者を悩ませるプロシージャ分割をマスターする極意 - t-hom’s diary

ただし、あまり細かくし過ぎると行数が増えてかえって管理が大変になるばかりなので、内容によっては2~3個の処理を1つのプロシージャにまとめることもある。

目安としては、1プロシージャあたりPCのディスプレイ1枚分(20~30行)くらい。
…区切るサイズや場所には個人差もあると思うので、絶対ではない。

[例]処理をざっくり分割

上記のの場合、ざっくり下記のように分けられると思う。


  • フォルダを確認
  • フォルダ内に処理対象のブックがあるか確認する
  • パスを取得
    • 1つ目のファイル名を取得
    • ファイル名とフォルダの場所からフルパスを取得
    • パスを取得
  • 値を取得
    • パスを指定してブックを開く
    • シートを取得
    • テーブルを取得
    • データ範囲を取得
    • 二次元配列として値を取得
  • 値を置き換える
    • セルの値を取得
    • 文字列に変換
    • 文字列を置き換える
    • セルの値を置き換える
    • シートの数だけ繰り返す
  • ブックを保存する
    • ブックの拡張子付きファイル名を取得
    • 現在のファイル名から新しいファイル名を取得
    • 格納先のフォルダを取得
    • ファイル名とフォルダの場所からフルパスを取得
    • 新しいパスでブックを保存する
  • ブックの数だけ繰り返す
  • メッセージボックスで「完了」をお知らせ。

出来るだけ共通の処理を抽象化する

「他のブックでもこのマクロを使うとしたら?」と考えながら、プロシージャや変数、引数の名前を考える。

[例]処理の抽象化

たとえば…

変更 関数名
⚫️⚫️社Bookの全シートの文字列を▼▼に置き換える
全文字列を置き換える(ワークブック置き換え前置き換え後

処理を分類してメソッド化

似たようなプロシージャをまとめる

今回の例であれば、「ファイル名とフォルダの場所からフルパスを取得」という処理が複数回登場していて、やることは共通している。

その前後にある「フォルダのパスやファイル名を『なんやかんや』する」処理も、「パスの操作」という意味で似ている。
このように、似たものを操作するプロシージャを分類して、いくつかのカテゴリに分けてみる。

さらに、標準モジュール(もしくはシートモジュール)にメイン処理用のプロシージャを作って、こちらから部品化・カテゴリ分けしたプロシージャを呼び出すことにする。

[例]プロシージャの分類

今回の例であれば、ざっくりこんな感じに分けられそう。

  • メイン・プロシージャ
  • 処理対象のブックの判定
  • パスの操作
  • ブックを開く、保存する
  • シートの値の取得
  • 文字列の操作

※「パスの操作」は、プロシージャのサイズによっては「文字列の操作」にまとめても良いかもしれない。

メイン処理以外をオブジェクトモジュール化する

メインのプロシージャ以外を、プロシージャのカテゴリごとに別々のクラスモジュール(やシートモジュール)として独立させる。

プロシージャのスコープを分ける

モジュール内専用の処理外部から呼び出せる処理(=メソッド)をそれぞれ区別し、スコープを設定しておく。
こうすることで、パブリックのものだけ入力補完が効くようになり、この後のコーディングが楽になる。

スコープのキーワード
スコープ キーワード 呼び方
全モジュール共通 Public パブリック・モジュール・レベル
モジュール内専用 Private プライベート・モジュール・レベル
クラス化のメリット

クラスの中で処理や値のスコープをPrivate以下にすると、外部のモジュールからは内部処理やデータの状態が見えなくなる。
このことをオブジェクト指向的には隠蔽(いんぺい)と呼び、特に「クラス」といった枠の中に閉じ込めることカプセル化という。

こうすることで、外部から値の変更などの干渉を受けづらくなり、コードが少し安全になる(はず)。

※「隠蔽」や「カプセル化」の目的について、詳しくはこちらもご参照いただけたら幸いです。 オブジェクト指向って、なんだ? - ゆるおたノート

プロパティの設定

共通の引数を探す

同じものを参照・利用しているのであれば、まとめて「プロパティ」にする。
値や参照はプロパティに代入して、メソッド内ではプロパティから呼び出すようにすることで引数を減らせる。

また、クラスモジュール内でも、メソッドの中からMe.プロパティ名で呼び出せるようになる(後述)。
入力補完も効くので、コーディングの効率や可読性も上がる*3

プロパティの値をモジュールレベル変数とする

プロパティの中身を参照する時はProperty Getプロシージャを呼び出す。
しかし、Property Getプロシージャの戻り値には値を直接代入できないので、下記のような書き方はできない
<2019/10/14追記>
「戻り値に代入」はできます。作例も差し替えております。失礼いたしました…

Property Getプロシージャには値を直接代入できないので、下記のような書き方はできない。

'[クラスモジュール] Exampleクラス
Property Get プロパティ名()As 型
    プロパティ名 = '←直接の代入は出来ない
End Property
'[標準モジュール]
Sub test()
    Dim ex As New Example
    ex.プロパティ名 = 新しい値
End Sub

実行すると、下記のようなコンパイルエラーが発生する。

値の取得のみ可能なプロパティに値を設定することはできません。

このため、Property LetプロシージャProperty Setプロシージャを使って「値を設定」できるようにする(詳細は後述)。

このときに、プロパティではなく「変数」を経由して「値」を代入することで、間接的にプロパティの中身を変更できるようになる。
そんなわけで、今の段階でProperty Getプロシージャも変数の値を返すようにしておく。

[例]変数を経由するよう変更
'[クラスモジュール] Exampleクラス
Private 変数 AsProperty Get プロパティ名()As 型
    プロパティ名 = 変数
End Property
変数のスコープを分ける

この時に、プロシージャと同じように「プロジェクト全体で使用するもの」と「モジュール内で完結するもの」、「プロシージャ内で完結するもの」を整理して、スコープを調整しておく。

プロパティ用の変数でスコープを「プライベート・モジュール・レベル」にしておくことで、「このクラス専用」の変数とすることができる。

つまり、「このクラス専用」の変数は、プライベートなプロシージャと同じように他のモジュールからは呼び出せなくなり、「隠蔽」されていることになる。
(以下、当記事ではこの変数のことを便宜上「隠し変数」と呼ぶことにする。)

スコープのキーワード
スコープ キーワード 呼び方
全モジュール共通 Public パブリック・モジュール・レベル
モジュール内専用 Private/Dim プライベート・モジュール・レベル
プロシージャ内専用 Dim プロシージャレベル
コンストラクで「隠し変数」に代入する

Class_Initializeという特別なプロシージャを作ると、インスタンスの生成時に必ず呼び出され、自動でプロパティに値を設定するように出来る*4

ただし、上述のようにプロパティではなく隠し変数に値を代入するように書いておく。

[例]コンストラクで隠し変数に代入
Private 隠し変数1 AsPrivate 隠し変数2 AsPrivate 隠し変数3 As オブジェクト系の型
Private 隠し変数4 As オブジェクト系の型
 
Public Sub Class_Initialize()
    隠し変数1 =Call 必ず実行する処理 '追加処理を入れても良い
    隠し変数2 =Set 隠し変数3 = オブジェクト
    Set 隠し変数4 = 値の準備とか(引数) '関数も使える
End Sub
コンストラクを使いやすくする

Class_Initializeプロシージャは「引数を設定できない仕様」になっているので、インスタンスの初期値は固定になってしまう。
いつも同じ値にしたいとは限らないので、これでは少し使いづらいことがある。

そこで一工夫。

Initializeメソッド(名前は自分で分かりやすいように変えてもOK)を別途作って、インスタンス生成時に引数として値を渡しつつ呼び出すことにする。
※この場合は、Class_Initializeプロシージャは作成しなくても良い。

これで、インスタンスの生成時にまとめて任意の値を設定できる。
(別の言語では、このような処理をするメソッドを「コンストラク」と言う。)

[例]引数が使えるコンストラク
'[クラスモジュール] Exampleクラス
Private 隠し変数1 AsPrivate 隠し変数2 AsPrivate 隠し変数3 As オブジェクト系の型
Private 隠し変数4 As オブジェクト系の型
Private 隠し変数5 As オブジェクト系の型
 
Public Sub Initialize(ByVal 仮引数1 As, _
                      ByRef 仮引数2 As オブジェクト系の型)
    隠し変数1 = 仮引数1
    
    Call 必ず実行する処理
    隠し変数2 = '引数ではなく値を指定しても大丈夫
    
    Set 隠し変数3 = 仮引数2
    Set 隠し変数4 = 値の準備とか(引数)
    Set 隠し変数5 = オブジェクト 'オブジェクトも大丈夫
    
End Sub
'[標準モジュール]
Public Sub Main()
    
    Dim test As New Example
    'Initializeメソッドを呼び出してプロパティの初期化
    test.Initialize 仮引数1:=引数1, _
                    仮引数2:=引数2    
End Sub
終了処理を追加する

モジュールレベル以上の変数は、マクロの実行が完了しても値が破棄されないので、マクロを複数回実行する時などは注意が必要になってしまう。
Class_Terminateという特別なプロシージャを作ると、インスタンスが不要になった時に自動で終了処理(=Terminate)されるようにできる。

<2019/10/14追記>
当初、上記例の中で変数の初期化・破棄処理を書いておりましたが、ことりちゅん (id:Kotori-ChunChun)さんより下記の通りアドバイスを頂きました。

クラスはインスタンスを破棄した時点でメンバの変数は一緒に消失しますから、サンプルのTerminateのように変数の初期化は意味が無いです。

ことりちゅん (id:Kotori-ChunChun)さんのツイートより

これに従い、作例は下記に修正いたしました。ご指摘ありがとうございます!

[例]終了処理
Public Sub Class_Terminate()
    Call 必ず実行する処理 'ゴミデータのお掃除など
End Sub
Property Getプロシージャでプロパティに隠し変数を代入する

ここまで準備ができたら、プロパティの値を設定していく。

上述のように隠し変数を経由してプロパティに値を設定することで、外部のプロシージャからはインスタンス名.プロパティ名でプロパティの中身を見られるようになる。

[例]値を代入
Private 隠し変数 AsProperty Get プロパティ名()As '~処理~
    隠し変数 = 値
    プロパティ名 = 隠し変数
    
End Property
[例]オブジェクトの参照値を代入
Private 隠し変数 As オブジェクト系の型
 
Property Get プロパティ名()As オブジェクト系の型
    
    '~処理~
    Set 隠し変数 = オブジェクト
    Set プロパティ名 = 隠し変数
    
End Property
ちなみに…

外部ではなく同クラス内で呼び出す時は、Me.プロパティ名と書くことができる。

[例]同クラス内で呼び出し
'[クラスモジュール] Exampleクラス
'▼プロパティ
Private 変数 AsProperty Get プロパティA()As 型
    プロパティA = 変数
End Property
 
'▼メソッド
Public Function test()
    Debug.Print "このインスタンスのプロパティAは、現在" & Me.プロパティA & "の状態です。"
End Function
Property Let/Setプロシージャで、プロパティに代入出来るようにする

プロパティは、中身を見るだけでなく処理の途中で値を変えたくなるときもある。
そういう時は、Property Let/Setプロシージャで値を設定できるようにしておく。

これで、外部のモジュールからプロパティに値を代入できるようになるので、実用に耐える(はず)。

[例]プロパティに代入するプロシージャを追加
Private 隠し変数 AsProperty Let プロパティ名(仮引数 As)
    '処理
    隠し変数 = 仮引数
End Property

繰り返しになるが、プロパティの設定は隠し変数を経由する。

そうしないと、プロパティに代入後も「隠し変数」の値は変わらず、改めてプロパティを呼び出して中身を見たら「元の値に戻ってる?」なんて混乱することに…

あとがき

VBAの神々によれば、ここまでがクラス入門編だそうです。
私はここに至るまで半年以上かかってしまいました…

「分かったような分かんないような…」で何度も書いては消してを繰り返してるので、キレイな文章はもう放棄です。
話の整理は未来の私に託します。笑

慣れてきたら、プロパティを先に作り込んでからメソッドを作り始める方が、入力補完の助けも得られてもっと書きやすいかもですね。
「どの基準・どの単位でクラスにまとめるか?」もまだ感覚が掴めてないです。
数をこなして慣れるしかないんですかね…

このシリーズについて

初心者の頭でVBAでクラスを作成する方法の整理に挑戦しています。

連載目次

  1. オブジェクト指向って、なんだ? - ゆるおたノート
  2. 当記事【VBA】クラスの作り方を整理してみた(移行手順編) - ゆるおたノート
  3. 【VBA】クラスの作り方を整理してみた(基本用語編) - ゆるおたノート

注釈

*1:日本語の文法的に言うと「文節単位」?

*2:いつもお世話になっております!!
この記事に限らず、VBA使いの人は読んで損はないブログです。

*3:入力は補完に任せられるから、多少長い名前をつけても大丈夫。

*4:Initializeは「初期化」のこと

【Google Apps Script】よく使うChrome拡張機能とライブラリまとめ

ユーザーやアカウントを作成するたびに探すのにいつも手間取っちゃうので、ここにまとめておきます。

絶対必要なモノ

AppsScript Color

標準だと全体的に白っぽい上に似たような色が多いので、ハッキリしたダークテーマ(Darcula)を適用します。

Font Size Changer For AppsScript

標準だと小さくてちょっと読みづらいですね…
エディタ部分のフォントサイズを調整して、読みやすくしてくれます。

あるといいモノ

Google Apps Script Github アシスタント

書いたコードのバージョン管理に。
プッシュやプル、簡単な差分チェックなどができます。

ただし、README.mdなどの「GASに無い拡張子」がリポジトリ内にあるとエラーになるので要注意です。

Mouse Dictionary

GASの公式ドキュメントは英語ですね。
読めない単語にマウスポインターを当てると意味が表示されます。

リッチな方は自前の辞書も登録出来たり、慣れてる方はCSSをいじって見た目をカスタマイズ出来たりします。

Q Accelerator

調べ物すると、よくQiitaにお世話になります。よく分からないことも多いですが…

「いいね」と「ストック」がワンクリックでまとめて出来るようになります。
コメントは今だに怖いですが、楽しい記事や勉強になる記事は積極的にリアクションしたいです。

<2020/10/24追記>
その後、Qiita自体の仕様変更により、この機能は使えなくなってしまいました…
今までありがとうございましたm(._.)m

他にも、Qiitaの表示をいくつか変更したり投稿用のテンプレートの登録も出来るようです。

Evernote Web Clipper

こちらも調べ物のお供。
後で見返したい記事をEvernoteに「クリップ」してくれます。
ショートカットも設定できるようです。

また、ブラウザで検索する時に自分のノートの検索結果も出してくれるようになります。
忘れやすくて何度も探すことも多いので、時々助けられてます。

ライブラリ

Slack

GETとかPOSTとか、APIの色々を知らなくてもSlackを使えるようになります。

Chatwork

GETとかPOSTとか、APIの色々を(略)

Moment.js

時間の操作がシンプルになります。
ただし、型の扱いに注意が必要(過去記事)です。

<2020/10/24追記>
その後、このライブラリは非推奨になったようです…

As of September 2020, Moment gets over 12 million downloads per week! However, Moment was built for the previous era of the JavaScript ecosystem.

(中略)

We recognize that many existing projects may continue to use Moment, but we would like to discourage Moment from being used in new projects going forward.

Moment.js | Docs

2020年までに、Momentは1,200万DL/週を獲得しました!しかし、MomentはJavaScriptのエコシステムより前の時代に制作されています。

多くのプロジェクトで使われ続ける可能性があることは我々も承知していますが、Momentを新規プロジェクトで使用され続けるのは避けたいと考えています。

【Google Apps Script × Gmail】下書きを量産するスクリプト

「メールを大量送信するので、下書きを大量に準備しておいてほしい」とのご依頼をいただきました。

曰く、「何件送信するか分からないので、とりあえず数百件作っといて!」とのことです。
スクリプトを書いて」などの指示は特にありませんでしたが、この量だと「どこかで転記ミスする未来」がハッキリと見えました。(怖)
しかも、手作業が苦手な私には…

クライアントさんに許可を頂いて、これを自動化してみました。

依頼内容

メールの書式は下記の通りです。

項目
To (空欄)
CC xxx@xxxx.xx
件名 ●●のお知らせ
本文 (太字やマーカーなど、装飾アリ)
添付ファイル PDF×2点

クライアントさんからのコメント

  • 本文はあらかじめ作成してあって、☆(スター)をつけたのでこれをコピーして使ってほしい。
  • Toの部分は、別の作業者が条件に沿ってマスター(並行して作成中)から転記して送信するので、空けておいて。

スクリプト

function Main() {
  // ★付きの下書きメールから本文をコピーする
  const STARED_NUM  = 5;
  var draftTemplate = getDraftTemplate(STARED_NUM);
  var htmlBody      = draftTemplate.getMessage().getBody();

  var options = {
    cc         : 'xxx@xxxx.xx',
    htmlBody   : htmlBody,
    // 所定のドライブに保存したファイルを添付ファイルとする
    attachments: getAttachmentsByFolderId('xxxxxxxxxxxxxxxxxxxxxxxx'),
  }
  
  // 引き数まとめ
  var args = {
    to       : '',
    title    : '●●のお知らせ',
    plainBody: '仮の本文',
    options  : options,
  };

  // 添付ファイルとあわせて下書きを作成する
  createDrafts(30, args) // 100通ずつで実行時間ギリギリ…
}

/**
 * 下書きボックスから指定した番号のメールを取り出す
 *
 * @param {number} n テンプレートとする下書きの番号(古いものからn件目)
 *
 * @return {object} 下書きオブジェクト
 */
function getDraftTemplate(n) {
  var drafts      = GmailApp.getDrafts();
  var draftCounts = drafts.length;
  
  // 最古からn番目にある、★付きの下書きメールを指定
  var targetIndex = draftCounts - n;
  var draftId     = drafts[targetIndex].getId();
  var draft       = GmailApp.getDraft(draftId);
  
  var msg = draft.getMessage().getDate();
  
  return draft;
}

/**
 * フォルダからファイルを取り出し、「Blob形式の配列」として添付ファイルをまとめる
 *
 * @param {string} folderId フォルダID
 *
 * @return {array} Blob形式データの配列
 */
function getAttachments(folderId) {
  var folder = DriveApp.getFolderById(folderId);
  var files  = folder.getFiles(); // 指定フォルダ内のイテレータを取得

  // Blob形式でファイルを配列化
  var attachments = [];
  while (files.hasNext()) {
    attachments.push(files.next());
  };
  
  return attachments;
}

/**
 * 下書きを量産する
 *
 * @param {number} max   作成する件数
 * @param {object} args .createDraftメソッドの引き数をまとめたオブジェクト
 */
function createDrafts(max, args) {
  for (var i = 0; i < max; i++) {
    GmailApp.createDraft(args.to, args.title, args.plainBody, args.options);
    
    var creationCount = i + 1;
    Logger.log('現在: ' + creationCount + ' 通目');
  }
}

補足

本文の表現

メール本文に太字やマーカー等の書式が設定されている場合や、メルマガのように文中に画像が挿入されている場合、内部的には「HTML形式」で表現されています。
Outlookの「リッチテキスト形式」なども同じはず。)

GmailMessageオブジェクトから.getBody()メソッドを呼び出すと、本文を「HTML形式」として取得できます。

const STARED_NUM  = 5;
var draftTemplate = getDraftTemplate(STARED_NUM);
var htmlBody      = draftTemplate.getMessage().getBody();

これをMain関数でoptionsオブジェクトのhtmlBodyプロパティに設定して、下書きを大量生産します。

Blobとは?

下記の変数filesに代入した時点では、まだファイルとしては実体がありません。

var folder = DriveApp.getFolderById(folderId);
var files  = folder.getFiles(); // 指定フォルダ内のイテレータを取得

ここまでだと、FileIteratorオブジェクトなる「イテレータ」を取得しただけの状態とのこと。

An iterator that allows scripts to iterate over a potentially large collection of files. File iterators can be acccessed from DriveApp or a Folder.

Class FileIterator  |  Apps Script  |  Google Developers

潜在的に巨大なファイルの集合体を、スクリプトでたどれるようにするイテレータ。「File iterator」は、DriveAppオブジェクトか、フォルダからのみアクセスできる。

イテレータと言うと「ループの処理でよく使う数値のこと?」と思いましたが、それは違うようです。(勉強中)

イテレータ(英語: iterator)とは、プログラミング言語において配列やそれに類似する集合的データ構造(コレクションあるいはコンテナ)の各要素に対する繰り返し処理の抽象化である。実際のプログラミング言語では、オブジェクトまたは文法などとして現れる。JISでは反復子(はんぷくし)と翻訳されている。

イテレータ - Wikipedia

まだちょっとよく分からないけど、GASでは「抽象化した結果、数値で表現している」ということでしょうか…?

そして話は戻りますが、ここで取得したイテレータを使ってフォルダ内のファイルを配列として格納します。

// Blob形式でファイルを配列化
var attachments = [];
while (files.hasNext()) {
  attachments.push(files.next());
};

.next()メソッドで初めて、いわゆる「ファイル」として実体を現した状態です。
その名も「Blob」*1

ただ、これもスプレッドシートやPDFなどといった保存形式ではなく、文字列や画像、色など、種類が混ざったデータも含め、コンピュータ用にすべて2進法の01だけで表現し直して、データベースに直接格納する方式だそうです。

この「Blob形式」でGmailDraftオブジェクトのプロパティに設定して、生成したメールをユーザーが開くと、元の「ファイル」として表現されるということですね。

処理が重い…

今回の処理では、1回あたり100通で実行時間ギリギリでした。
PDFファイルは数MB単位だったので、結構処理に時間がかかっている印象です。

ちゃんと検証はしていませんが、「フォルダからファイルを取得 → Blobに変換」のあたりで時間がかかっているのかなと推測しています。

なお、これを少し書き換えると、処理速度が上がるようです(後述)。

設定値の動的な取得

今回は、宛先や添付ファイルの格納フォルダなどをスクリプト内で直接指定しています。

しかし、制限時間がある中で急いで書いていたので、この後あることに気付きました。
(制限時間よりも私の頭が硬いせいな気もしますが、それは置いといて…)

例えば、下書きを「送信する直前の状態」まで編集しておいて、そこから取得する形にすれば、より正確な複製(かつ読みやすいスクリプト)が出来るはずです。
それでも値が間違えていたなら、それは下書きのせいだから…

というわけで、少し書き換えてみました。
VBAWith構文のような表現が使えたらもっとスッキリするんだろうなぁ…)

// ★付きの下書きメールをもとに複製する
const STARED_NUM  = 5;
var draftTemplate = getDraftTemplate(STARED_NUM);
var draftMessage  = draftTemplate.getMessage();

var options = {
  cc         : draftMessage.getCc(),
  htmlBody   : draftMessage.getBody(),
  attachments: draftMessage.getAttachments(),
}

// 引き数まとめ
var args = {
  to       : draftMessage.getTo(),
  title    : draftMessage.getSubject(),
  plainBody: draftMessage.getPlainBody(),
  options  : options,
};

GmailMessageオブジェクトを変数draftMessageに格納して、そこから値を引っ張るかたちです。
自分の環境で比べてみたところ、処理時間もこちらの方が速いようでした。

このことから、添付ファイルも、フォルダに格納するより直接下書きに貼り付けておくのが良さそうです。

蛇足ですが…

「確認しつつ送信」が必要であれば、今回の処理で問題無いかと思います。

ただ、もし宛先の条件がハッキリしていて一定であれば、本当は下書きの準備だけでなく送信まで一気にGASへお任せした方が良かった気がしています。
もう少し詳しくお話伺ってみれば良かったな。いま言っても後の祭りですが…

ブログ記事も「大量の」下書きの話は見つけられなくて、送信まで行うものが多いような。
需要が無いということなのかもしれませんが、目的に合わせて使い分けていただければと思います。

参考


*1:Binary Large OBject(バイナリ・ラージ・オブジェクト)の略。

【Git勉強中】リポジトリの作成と接続

たぶん、手順的にはリモートリポジトリを先に作る方が楽で簡単だと思います。
思うんですが、なぜかローカルで作業始めちゃってから気付くんです…

はじめに

基本の流れ

Git自体はじめての方は、まずはこちらからどうぞ。

【Git勉強中】操作に慣れてきたので、流れを整理してみました。 - ゆるおたノート

凡例

記号・用語 意味 説明
$ コマンドライン」で使えるコマンド 通常、Gitを始めとする「シェルスクリプト」系の説明では、コマンドの文頭に$をつけて表現されることが多いようです。
当記事でもそれに倣って記載しています。

実際にコマンドを入力するときは、git~以下をコピペしてください。
# コメント 補足事項など。
(対話モードでは使えません、、、)
<> 編集点(という表現で良いのかな…?) 任意の値(名前、識別子など)を入力してください。
(コミットの)識別子 コミットごとに付与される半角英数字7桁の番号。 SHA-1というハッシュ値だそうです。
当記事では<コミット>と表記します。
ディレクト ファイルの入れ物、つまりフォルダのこと。 当記事では、(特に言及がない限りは)絶対パス相対パスどちらの指定でも可です。

▼選択してください

リポジトリを…

ローカルリポジトリを作成し、リモートリポジトリに接続する場合

【1】任意のディレクトリに移動

cdchange directoryの略ですね。

$ cd <任意のディレクトリ>

【2】ローカルリポジトリの作成

Initialize(初期化)して、現在のディレクトリでGit管理を始めます。

$ git init

.gitというディレクトリが作成されますが、名前が.始まりなので自動的に隠しファイル扱いになります。
つまり最初は「見えない」ので、「え!どこ行った!?」と混乱すると思います。笑

Gitに慣れてきたら、その中にあるCONFIGファイル等の設定データを触る必要も出てきます。
必要に応じて、WindowsエクスプローラーやmacOSのFinderで隠しファイルを表示するように設定しておくことをオススメします。

【3】ローカルリポジトリで1度コミットしておく

後ほどリモートリポジトリにプッシュしますが、その時にコミット履歴無しのままだとエラーが出て怒られます。

error: src refspec master does not match any
error: failed to push some refs to '<リモートリポジトリ>'

そこで、プッシュの前に1度ステージングからコミットまでを行っておきます。
詳しくは下記記事をご参照ください。

【Git勉強中】ステージに上げたり下げたり。 - ゆるおたノート 【Git勉強中】ステージした変更を記録する - ゆるおたノート

【4】リモートリポジトリを作成する

通常はGitHub(もしくはBitBucket)が選択肢になるかと思います。
リポジトリの作成手順は、使用するサービスによって異なるため割愛します。

GitHubの場合は、アカウント作成後にメアドの設定もしておくことをオススメします!
(詳しい手順は下記のサイトが参考になるかと思います。) GitHub でダミーのメールアドレスを使用する - Qiita

【5】ローカルリポジトリリモートリポジトリに紐付ける

HTTPS接続の場合

リポジトリのURLを指定して呼び出します。

git remote add origin <リモートリポジトリのHTTPS接続用アドレス>

GitHubの場合、アドレスは下記のような文字列です。

https://github.com/ユーザー名/リモートのリポジトリ名.git

SSH接続の場合

初期設定がちょっとめんどくさいけど、HTTPS接続よりちょっと安全(のはず)です。

(1) 端末でSSHキーを作成し、リモートリポジトリのアカウントに登録する

GitHub向けの記事ですが、SSHキーの作成についてはこちらが参考になると思います。 GitHubでssh接続する手順~公開鍵・秘密鍵の生成から~ - Qiita

秘密鍵は、心情的に別の場所に保存したいところなのですが、移動しない方が良いみたいですね…?
参考:[SSH]秘密鍵の保存場所はどこがいいのか? | 東京伊勢海老通信
<2020/10/10追記>
その後、こちらのページはアクセスできなくなったようです…

(2) ローカルリポジトリをリモートリポジトリに紐付ける
$ git remote add origin <リモートリポジトリのSSH接続用アドレス>

GitHubの場合、アドレスは下記の文字列です。

git@github.com:ユーザー名/リモートのリポジトリ名.git

【6】リモートリポジトリにプッシュする

そのままプッシュすると、リモート側のデータとコンフリクトしてしまいます。
初めてのプッシュのはずなのでちょっと腑に落ちないのですが…)
<2019/12/20 追記>
README.mdなど「何かしらのファイル」がリモートリポジトリにある場合に、ローカルリポジトリとの差分が発生してしまうようです。

<2019/07/03 追記>
エラーメッセージを追加しました。

# 入力
$ git push origin master
 
#エラーメッセージ
To github.com:xxxxxxxx.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'git@github.com:xxxxxxxx.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

「git@github.com:xxxxxxxx.git」へのプッシュは失敗しました。
ローカル端末に無い変更履歴がリモート側に保存されているため、更新が拒否されました。
~以下略~

そうならないためには、(あくまで最終手段として)-fオプションをつけてローカル側の内容で強制的に上書きします。

$ git push -f origin master

-fオプションについては、詳しくは過去記事をご参照ください。

【7】完了。

あとは、コミットとプッシュ・プルの繰り返し。

関連記事は、こちら

リモートリポジトリを作成し、ローカルにクローンのリポジトリを作成する場合

【1】リモートリポジトリを作成する

使用するサービスによって手順が異なるため、(略)。

メールアドレスの登録については、前述のリンク先を参照してください。

【2】(SSH接続の場合は)端末でSSHキーを作成し、リモートリポジトリのアカウントに登録する

詳しくはこちら

【3】ローカルで任意のディレクトリに移動

$ cd <任意のディレクトリ>

【4】リモートリポジトリのクローンをローカルに作成する

アドレスはHTTPS用、SSH用、どちらでも可能です。

$ git clone <リモートリポジトリのアドレス>

cloneで以下4つのコマンドを兼ねます。

  • init(≒ローカルリポジトリの初期化)
  • pull(≒リモートリポジトリからダウンロード)
    • fetch(≒リモートと同期)
    • merge(≒ローカル内での同期)

【5】完了。

あとは、コミットとプッシュ・プルの繰り返し。

このシリーズについて

Gitのコマンドについて、勉強しつつ記事にまとめています。

誤り、分かりづらい等ありましたら、ぜひコメント欄Twitterお問い合わせフォーム等でご教示ください!

連載目次

  1. 【Git勉強中】操作に慣れてきたので、流れを整理してみました。 - ゆるおたノート
  2. 【Git勉強中】ブランチの移動を使い分けたい - ゆるおたノート
  3. 【Git勉強中】ステージに上げたり下げたり。 - ゆるおたノート
  4. 【Git勉強中】ステージした変更を記録する - ゆるおたノート
  5. 【Git勉強中】あっ!そのコミット訂正させてください! - ゆるおたノート
  6. 【Git勉強中】自分のコミット履歴を提出する - ゆるおたノート
  7. 当記事【Git勉強中】リポジトリの作成と接続 - ゆるおたノート

参照

Gitでローカルリポジトリを作成して、後にリモートリポジトリへ反映する - Qiita error: src refspec master does not match anyが出る時(解決済み) - Qiita いまさら聞けないgitの使い方 - Qiita git fetchの理解からgit mergeとpullの役割 - Qiita git clone と git pull の違い(メモ) - Qiita githubの複数アカウントを使い分けるためにHTTPとOAuthTokenをつかう - Qiita

【Git勉強中】自分のコミット履歴を提出する

開発用のブランチで編集・コミットが完了したら、本丸のmasterブランチにも反映させます。

はじめに

基本の流れ

Git自体はじめての方は、まずはこちらからどうぞ。

【Git勉強中】操作に慣れてきたので、流れを整理してみました。 - ゆるおたノート

凡例

記号・用語 意味 説明
$ コマンドライン」で使えるコマンド 通常、Gitを始めとする「シェルスクリプト」系の説明では、コマンドの文頭に$をつけて表現されることが多いようです。
当記事でもそれに倣って記載しています。

実際にコマンドを入力するときは、git~以下をコピペしてください。
# コメント 補足事項など。
(対話モードでは使えません、、、)
<> 編集点(という表現で良いのかな…?) 任意の値(名前、識別子など)を入力してください。
(コミットの)識別子 コミットごとに付与される半角英数字7桁の番号。 SHA-1というハッシュ値だそうです。
当記事では<コミット>と表記します。

マージ

ブランチで編集が出来たら、一旦ローカルリポジトリmasterブランチに反映させます。

【A】お互いの履歴やマージの記録自体も残しつつ、マージする場合

[書き方]

--no-ffオプションを指定してFast-Forwardとさせないことで、マージの履歴も含めて記録させます。

$ git merge --no-ff <コミット履歴のあるブランチ>

Fast-Forwardの意味については、こちらの41ページあたりが参考になりました。

[例]

masterブランチとdevelopブランチの両方の履歴を残します。

# masterブランチに居る状態で…
$ git merge --no-ff develop

【B】一方の内容のみmasterブランチへ反映させる場合

[書き方]

【A】に対し、--ffFast-Forwardと指定して、片方の編集内容のみ残します。

$ git merge --ff <コミット履歴のあるブランチ>

ただし、mergeされる側にも編集履歴があると、「コンフリクト」した状態になるためマージできません。
※この場合は、いったん編集履歴を破棄してから受け入れるか、--no-ffで両方を残すかになると思います。

[例]

masterブランチにdevelopブランチの履歴をコピーします。

# masterブランチに居る状態で…
$ git merge --ff develop

プッシュ

ローカルリポジトリで編集が終わったら、リモートリポジトリにも情報を反映させます。

【A】同名のブランチにプッシュする場合

[書き方]

これで編集履歴<ローカルブランチ>から<リモートリポジトリ>に送る、という意味になります。

$ git push <リモートリポジトリ> <ローカルブランチ>
[例]

ローカルリポジトリmasterブランチから、リモートリポジトリoriginの同名ブランチ(=master)にコミット履歴をプッシュ。

$ git push origin master

【B】ブランチ名を指定してプッシュする場合

[書き方]

リモートリポジトリでもブランチが切られている場合など、プッシュ先のブランチを指定するときは、末尾に:<リモートブランチ>と付け加えます。

$ git push <リモートリポジトリ> <ローカルブランチ>:<リモートブランチ>
[例]

ローカルリポジトリmasterブランチから、リモートリポジトリoriginbranch1ブランチにコミット履歴をプッシュ。

$ git push origin master:branch1

【C】強制的にプッシュして上書きする場合

[書き方]

そのままプッシュするとリモートリポジトリの履歴とコンフリクトしてしまう場合など、どうしてもプッシュ元の情報を反映させたい時のみ-fオプションを使用します。

$ git push -f <リモートリポジトリ> <ローカルブランチ>
$ git push --force <リモートリポジトリ> <ローカルブランチ>
[例]

ローカルリポジトリmasterブランチの内容で、リモートリポジトリoriginの同名ブランチを強制的に上書き。

$ git push -f origin master

▼ここまでのまとめ

ここまでの操作をまとめると、以下の流れになります。

[例]
# [develop]ブランチに移動
$ git checkout develop
 
# ~ 編集 in [develop]ブランチ ~
 
# 今回の編集内容をまとめてステージに上げる
$ git add -A
 
# 一旦ステージの状態を確認
$ git status
 
# 問題がなければコミットする
$ git commit -m 'test.'
 
# ここまでのコミット履歴を確認
$ git log
 
# 問題がなければ[master]ブランチに移動
$ git checkout master
 
# [develop]ブランチの履歴を[master]ブランチに反映する
$ git merge --no-ff develop
 
# 今回のコミット履歴をリモートリポジトリ[origin]の[master]ブランチに反映する
$ git push origin master

このシリーズについて

Gitのコマンドについて、勉強しつつ記事にまとめています。

誤り、分かりづらい等ありましたら、ぜひコメント欄Twitterお問い合わせフォーム等でご教示ください!

次回

【Git勉強中】リポジトリの作成と接続 - ゆるおたノート

連載目次

  1. 【Git勉強中】操作に慣れてきたので、流れを整理してみました。 - ゆるおたノート
  2. 【Git勉強中】ブランチの移動を使い分けたい - ゆるおたノート
  3. 【Git勉強中】ステージに上げたり下げたり。 - ゆるおたノート
  4. 【Git勉強中】ステージした変更を記録する - ゆるおたノート
  5. 【Git勉強中】あっ!そのコミット訂正させてください! - ゆるおたノート
  6. 当記事【Git勉強中】自分のコミット履歴を提出する - ゆるおたノート
  7. 【Git勉強中】リポジトリの作成と接続 - ゆるおたノート

参照

マージ

こわくない Git Git - git-merge Documentation

プッシュ

git push コマンドの使い方と、主要オプションまとめ | WWWクリエイターズ

【Git勉強中】あっ!そのコミット訂正させてください!

うっかり間違えても訂正できます💪

はじめに

基本の流れ

Git自体はじめての方は、まずはこちらからどうぞ。

【Git勉強中】操作に慣れてきたので、流れを整理してみました。 - ゆるおたノート

凡例

記号・用語 意味 説明
$ コマンドライン」で使えるコマンド 通常、Gitを始めとする「シェルスクリプト」系の説明では、コマンドの文頭に$をつけて表現されることが多いようです。
当記事でもそれに倣って記載しています。

実際にコマンドを入力するときは、git~以下をコピペしてください。
# コメント 補足事項など。
(対話モードでは使えません、、、)
<> 編集点(という表現で良いのかな…?) 任意の値(名前、識別子など)を入力してください。
(コミットの)識別子 コミットごとに付与される半角英数字7桁の番号。 SHA-1というハッシュ値だそうです。
当記事では<コミット>と表記します。

コミット取り消し

【A】直前のコミット取り消す

[a]ブランチのコミット履歴のみ書き換える場合

git addしているインデックスと、作業ツリーはそのままにします。

$ git reset --soft <ブランチ名>
(例)
$ git reset --soft HEAD^
[b]ブランチのコミット履歴とインデックスを書き換える場合
(※デフォルト)

作業ツリーのみ残ります。

$ git reset --mixed <ブランチ名>

なお、git resetmixedモードがデフォルトなので、↑のコマンドは下記のようにも書けます。

$ git reset <ブランチ名>
[c]作業ツリーも含めてすべて書き換える場合

一つ前のコミット履歴を作成した直後の状態に完全に巻き戻します。
(それまでの変更も含めて)何もなかった状態になります。

$ git reset --hard <ブランチ名>

git reset --hard は、ブランチの歴史を強制的に書き換えてしまう強力なコマンドです。
もしマージコミットをpushしてないのであれば、強気で使ってしまってよいでしょう。

~中略~

もし保存していない変更が作業ツリーやインデックスにあれば、消し飛びますので、実行前にgit statusでなにか作業が残っていないか確認してみて下さい。

git merge の取り消し方法。reset と revert コマンドについて。 | WWWクリエイターズ

【B】複数のコミットをまとめて取り消し

引数に<ブランチ名>ではなく<コミット>を指定すると、(現在のブランチの)特定のコミットの状態に戻すことが出来ます。

$ git reset --hard <コミット>

【C】間違えたコミット打ち消し用のコミットを作成

[a]基本の使い方

新しくコミットを作成するのでブランチの過去履歴には影響を与えずに済み、pushのコンフリクトを防止します。

$ git revert
$ git revert <ブランチ名>

なお、mergeのコミットを打ち消す時は、注意が必要のようで…

  • 参考記事
    (まだ詳細読んでない…あとで読みます…たぶん…)
[b]コミットメッセージはそのままにする場合

オプションとして--no-editを付加。

$ git revert --no-edit <コミット>

【D】「取り消し」の取り消し

[a]基本の使い方
(1)「打ち消しコミット」も含めた履歴を確認する

git reflogで、HEADを含めたこれまでのコミット履歴(=「参照」の移動遍歴)を見ることができます。
「reflog」は「reference log」の略ですかね…?

ここで「コミットの巻き戻し先」を確認します。

$ git reflog

すると、ターミナルでコミット履歴が出力されます。
1番上が最新で、何か行う毎に記録されていることが分かります。

※私の環境では、このようになりました。

3e7182e (HEAD -> develop, master) HEAD@{0}: checkout: moving from master to develop
3e7182e (HEAD -> develop, master) HEAD@{1}: commit: fix directory description and change heading positions.
ba3303d HEAD@{2}: commit: fix the css property table.
c14f55a (origin/master, origin/HEAD) HEAD@{3}: commit: add Table of Contents.
3ef84f7 HEAD@{4}: checkout: moving from master to master
3ef84f7 HEAD@{5}: commit: re-edit directories.
6d75462 HEAD@{6}: commit: change indent from tabs to spaces.
909e2a9 HEAD@{7}: commit: edit filename.
df8920d HEAD@{8}: commit (merge): move to several directories.
d616027 HEAD@{9}: clone: from https://github.com/yuricks7/xxxxxxxx
  • 意味

    識別子(HEAD -> ソース, 行き先) HEADから●番目: アクション: コメントor概要

(2)指定のコミットに巻き戻す

ブランチに残っているコミット履歴を、先ほど確認した巻き戻し地点の状態に戻します。

git resetに、ブランチ名ではなくHEADの番号を指定すると「●個前のHEADの状態」に戻すことが出来ます。

$ git reset --hard HEAD@{●●}
(例)

ここまでをまとめると、下記のような流れになります。

# 入力
$ git reflog
 
# 結果
3e7182e (HEAD -> develop, master) HEAD@{0}: checkout: moving from master to develop
3e7182e (HEAD -> develop, master) HEAD@{1}: commit: fix directory description and change heading positions.
ba3303d HEAD@{2}: commit: fix the css property table.
c14f55a (origin/master, origin/HEAD) HEAD@{3}: commit: add Table of Contents.
3ef84f7 HEAD@{4}: checkout: moving from master to master
3ef84f7 HEAD@{5}: commit: re-edit directories. # ← ここに戻したいとき
6d75462 HEAD@{6}: commit: change indent from tabs to spaces.
909e2a9 HEAD@{7}: commit: edit filename.
df8920d HEAD@{8}: commit (merge): move to several directories.
d616027 HEAD@{9}: clone: from https://github.com/yuricks7/xxxxxxxx
 
# HEAD@{5}の時点に強制巻き戻し
$ git reset --hard HEAD@{5}

コミット修正

【A】直前のコミット修正して上書き

[a]基本の使い方

直前の変更を破棄して、新しいコミットが作成されます。

$ git commit -a
$ git commit --amend

コミットの識別子も変更されることに注意です!

[注意]「push済みのコミット」とコンフリクトしないように注意!

修正前の内容で一度リモートにpush済みの場合、その後にコミット内容を修正するとリモート側とコンフリクトが発生してしまいます。
つまり、そのままでは再pushはできません。めんどくさい…

どうしても修正後の内容で記録したい場合は、再pushの際に-fオプションをつけて新しい内容で強制的に上書きが必要です。

# 強制的に<ブランチ名>へPushする
$ git push -f origin <ブランチ名>
$ git push --force origin <ブランチ名>

ただし、チームで開発しているときなど、複数人が参照しているブランチ(master等)ではさらにコンフリクトが発生する原因になるため、この方法は避けた方が良いようです。

【B】コミットをまとめる

[a]基本の使い方

現在のブランチで、それまでのコミットを<コミット>まで1つにまとめます。

$ git rebase -i <コミット>
$ git rebase --interactive <コミット>

詳しい手順の解説は、こちらの記事が参考になると思います。

[注意]「push先リポジトリ内の履歴」とコンフリクトしないように注意!

「rebase前の履歴」を既にリモートへpush済みの場合、「rebase後の履歴」とコンフリクトしてしまいます。
つまり、これもそのままでは再pushはできません。めんどくさい…

後者の適用で問題なければ、下記のコマンドで強制的にリモート側の履歴を書き換えます。

# 強制的に<ブランチ名>へPushする
$ git push -f origin <ブランチ名>
$ git push --force origin <ブランチ名>

ただし、前述のように複数人が参照しているブランチではこの方法は避けた方が良いようです。

このシリーズについて

Gitのコマンドについて、勉強しつつ記事にまとめています。

誤り、分かりづらい等ありましたら、ぜひコメント欄Twitterお問い合わせフォーム等でご教示ください!

次回

【Git勉強中】自分のコミット履歴を提出する - ゆるおたノート

連載目次

  1. 【Git勉強中】操作に慣れてきたので、流れを整理してみました。 - ゆるおたノート
  2. 【Git勉強中】ブランチの移動を使い分けたい - ゆるおたノート
  3. 【Git勉強中】ステージに上げたり下げたり。 - ゆるおたノート
  4. 【Git勉強中】ステージした変更を記録する - ゆるおたノート
  5. 当記事【Git勉強中】あっ!そのコミット訂正させてください! - ゆるおたノート
  6. 【Git勉強中】自分のコミット履歴を提出する - ゆるおたノート
  7. 【Git勉強中】リポジトリの作成と接続 - ゆるおたノート

参照

【Git勉強中】ステージした変更を記録する

いよいよ「Gitの本番」って感じです!

はじめに

基本の流れ

Git自体はじめての方は、まずはこちらからどうぞ。

【Git勉強中】操作に慣れてきたので、流れを整理してみました。 - ゆるおたノート

凡例

記号・用語 意味 説明
$ コマンドライン」で使えるコマンド 通常、Gitを始めとする「シェルスクリプト」系の説明では、コマンドの文頭に$をつけて表現されることが多いようです。
当記事でもそれに倣って記載しています。

実際にコマンドを入力するときは、git~以下をコピペしてください。
# コメント 補足事項など。
(対話モードでは使えません、、、)
<> 編集点(という表現で良いのかな…?) 任意の値(名前、識別子など)を入力してください。
(コミットの)識別子 コミットごとに付与される半角英数字7桁の番号。 SHA-1というハッシュ値だそうです。
当記事では<コミット>と表記します。

コミット

【A】既にステージに上がっている変更内容をまとめてコミット

引数なしで実行します。

$ git commit

【B】変更のあったファイルをインデックスに追加しつつ、まとめてコミット

git add .git commitの合わせ技。

$ git commit -a
$ git commit --all

ただし、新規作成されたファイルは対象外なので、別途git addでステージしてからコミットする必要があります。

【C】ファイルやフォルダを1つずつ指定してコミット

$ git commit <ファイル名/フォルダ名>
[注意].gitignoreに該当するファイルに注意!

.gitignoreに記載のあるファイルはステージされないため、コミットにも含められずエラーになります。

# 入力
$ git commit <ファイル名>
 
# 結果
error: pathspec '<ファイル名>' did not match any file(s) known to git.

「<ファイル名>」は、gitが検知しているファイルにはマッチしませんでした。

【D】カレントディレクトリを指定して、まとめてコミット

引数として相対パス.(ピリオド)をつけます。

$ git commit .

コミットメッセージの入力

【A】コミットメッセージを入力しつつコミット

コミット後にテキストエディタで入力する手間(後述)が減ります。
ただし、入力している文字数は確認できないので、何かしら対策が必要かも…?*1

$ git commit . -m '<コメント>'
$ git commit . --message='<コメント>'

※後者は=が必要!

【B】コミットメッセージに段落をつける

オプション-m <コメント>1つにつき1つずつ段落化されます。
これを利用して、要約→詳細のように表現できます。

$ git commit . -m '<コメント>' -m '<詳細コメント>'
[例]
# 入力
$ git commit -m "test1." -m "test2!" -m "it's test3!!"
 
# 結果
[develop c115340] test1.
 1 file changed, 1 insertion(+), 1 deletion(-)
 
# コミット内容を確認
$ git log
 
# 結果
commit c11534072071664c079cb709d2cabb32d8342db0 (HEAD -> develop)
Author: xxxxxxxx <xxxxxxxx@users.noreply.github.com>
Date:   Wed Jun 26 16:55:41 2019 +0900
 
    test1.
 
    test2.
 
    it's test3!

タイトル(Short Description)が「test1.」のコミット履歴が作成されました。

【C】エディタでコミットメッセージを入力してコミット

普段は↑のコマンドを使ってコミットメッセージを入れるので、これはあまり必要ないかと思います。

ただ、コメントを入れ忘れてしまった時にはエディタが自動で立ち上がります。
そのときに焦ってしまうので笑、一応記載しておきます。

  1. コマンドを打ちます。

    $ git commit
    

  2. 下記のメッセージと共にエディタが開きます。

    hint: Waiting for your editor to close the file...
    

    エディタのクローズ待ち…

  3. エディタで1行目にコメントを入力。

    ここにコメントを入力。
    # Please enter the commit message for your changes. Lines starting
    # with '#' will be ignored, and an empty message aborts the commit.
    #
    # On branch develop
    # Changes to be committed:
    #  modified:   index.html
    #
    

    コミットメッセージを入力してください。
    #で始まる行は無視しますが、メッセージが空の場合はコミットを中止します。
    (以下略)

  4. 入力を終えたらCtrl+Sで保存。

    ※飛ばすと怒られます。笑

    Aborting commit due to empty commit message.
    

    コミットメッセージが無いので、コミットは中止します。

  5. 保存できたら、Ctrl+Wでエディタを閉じます。

このシリーズについて

Gitのコマンドについて、勉強しつつ記事にまとめています。

誤り、分かりづらい等ありましたら、ぜひコメント欄Twitterお問い合わせフォーム等でご教示ください!

次回

【Git勉強中】あっ!そのコミット訂正させてください! - ゆるおたノート

連載目次

  1. 【Git勉強中】操作に慣れてきたので、流れを整理してみました。 - ゆるおたノート
  2. 【Git勉強中】ブランチの移動を使い分けたい - ゆるおたノート
  3. 【Git勉強中】ステージに上げたり下げたり。 - ゆるおたノート
  4. 当記事【Git勉強中】ステージした変更を記録する - ゆるおたノート
  5. 【Git勉強中】あっ!そのコミット訂正させてください! - ゆるおたノート
  6. 【Git勉強中】自分のコミット履歴を提出する - ゆるおたノート
  7. 【Git勉強中】リポジトリの作成と接続 - ゆるおたノート

参照

Git - Reference git commit コマンドの使い方と、主要オプションのまとめ | WWWクリエイターズ 基本的なGitコマンドまとめ - Qiita

注釈

【Git勉強中】ステージに上げたり下げたり。

恐らくcommitと合わせてかなりお世話になるであろうコマンド…

はじめに

基本の流れ

Git自体はじめての方は、まずはこちらからどうぞ。

【Git勉強中】操作に慣れてきたので、流れを整理してみました。 - ゆるおたノート

凡例

記号・用語 意味 説明
$ コマンドライン」で使えるコマンド 通常、Gitを始めとする「シェルスクリプト」系の説明では、コマンドの文頭に$をつけて表現されることが多いようです。
当記事でもそれに倣って記載しています。

実際にコマンドを入力するときは、git~以下をコピペしてください。
# コメント 補足事項など。
(対話モードでは使えません、、、)
<> 編集点(という表現で良いのかな…?) 任意の値(名前、識別子など)を入力してください。
(コミットの)識別子 コミットごとに付与される半角英数字7桁の番号。 SHA-1というハッシュ値だそうです。
当記事では<コミット>と表記します。
ディレクト ファイルの入れ物、つまりフォルダのこと。 当記事では、(特に言及がない限りは)絶対パス相対パスどちらの指定でも可です。

▼コミット予定に追加(=ステージング)する

【A】管理対象にあるファイルをすべて追加

$ git add -A
$ git add --all

【B】ファイル名やディレクトリを指定して追加

$ git add <ファイル名>
$ git add <ディレクトリ>

【C】現在のディレクトリの変更をすべて追加

.(ピリオド1つ)を使って、相対パスでカレントディレクトリを表現します。

$ git add .

ステージから下ろす

【A】インデックスから除外

該当のディレクトリ内でファイルを削除した場合など。

$ git rm -r --cached <ファイル名>
$ git rm -r --cached <ディレクトリ>
分類 用語 説明
コマンド rm removeの略
オプション -r recursive(再帰的、帰納的 / 反復的)の略(?)
<2019/12/20追記>
--cached
ファイル自体は残して、追跡をやめる。
※今後も記録が不要であれば、.gitignoreにも追加しておく。

ステージされたファイルを確認

【A】ステージに不足が無いか確認

$ git status
[例]何も上げていない場合
# 入力
$ git status
 
# 結果
On branch master
Your branch is up to date with 'origin/master'.
 
Last commands done (4 commands done):
   pick 2757f4b fix directory hierarchy.
   pick 467d0e2 fix directory hierarchy.
  (see more in file .git/rebase-merge/done)
No commands remaining.
You are currently editing a commit while rebasing branch 'master' on 'f71eb8a'.
  (use "git commit --amend" to amend the current commit)
  (use "git rebase --continue" once you are satisfied with your changes)
 
nothing to commit, working tree clean

コミット予定ナシ、作業ツリーも空です。

[例].gitignoreREADME.txtを修正して、.gitignoreはステージ済みの場合
# 入力
$ git status
 
# 結果
On branch master
Your branch is up to date with 'origin/master'.
 
Last commands done (4 commands done):
   pick 2757f4b fix directory hierarchy.
   pick 467d0e2 fix directory hierarchy.
  (see more in file .git/rebase-merge/done)
No commands remaining.
You are currently editing a commit while rebasing branch 'master' on 'f71eb8a'.
  (use "git commit --amend" to amend the current commit)
  (use "git rebase --continue" once you are satisfied with your changes)
 
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
 
        modified:   .gitignore
 
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
 
        modified:   README.md

コミット予定の変更履歴:
(ステージから下ろす場合はgit reset HEAD <file>...してください)

  変更あり:.gitignore

ステージされていない変更履歴:
(コミットする場合は、git add <file>...してください。)
(作業中ディレクトリの変更をコミットから除外する場合は、git checkout -- <file>...してください)

  変更あり:README.md

【B】変更をステージしつつ、ステージの一覧を表示

$ git add -v .
$ git add --verbose .
[例]何も上げていない場合
# 入力
$ git add -v .
 
# 結果
Nothing specified, nothing added.
Maybe you wanted to say 'git add .'?

ステージには何も指定されてません。コマンド間違えてませんか?

[例].gitignoreREADME.txtを修正して、.gitignoreはステージ済みの場合
# 入力
$ git add -v .
 
# 結果
add 'README.md'

'README.md'をステージに追加済み

先にステージしているファイルは出力してもらえないみたいです。
それならgit statusを使おうかな、結果は長くなっちゃうけど。

このシリーズについて

Gitのコマンドについて、勉強しつつ記事にまとめています。

誤り、分かりづらい等ありましたら、ぜひコメント欄Twitterお問い合わせフォーム等でご教示ください!

次回

【Git勉強中】ステージした変更を記録する - ゆるおたノート

連載目次

  1. 【Git勉強中】操作に慣れてきたので、流れを整理してみました。 - ゆるおたノート
  2. 【Git勉強中】ブランチの移動を使い分けたい - ゆるおたノート
  3. 当記事【Git勉強中】ステージに上げたり下げたり。 - ゆるおたノート
  4. 【Git勉強中】ステージした変更を記録する - ゆるおたノート
  5. 【Git勉強中】あっ!そのコミット訂正させてください! - ゆるおたノート
  6. 【Git勉強中】自分のコミット履歴を提出する - ゆるおたノート
  7. 【Git勉強中】リポジトリの作成と接続 - ゆるおたノート

参照

Git - git-add Documentation

git add コマンドの使い方と、主要オプション | WWWクリエイターズ

recursiveの意味・使い方・読み方 | Weblio英和辞書

【Git勉強中】ブランチの移動を使い分けたい

これは覚えることがあまり無いですが、「branchを切り替えて編集」がまだ慣れません…

はじめに

基本の流れ

Git自体はじめての方は、まずはこちらからどうぞ。

【Git勉強中】操作に慣れてきたので、流れを整理してみました。 - ゆるおたノート

凡例

記号・用語 意味 説明
$ コマンドライン」で使えるコマンド 通常、Gitを始めとする「シェルスクリプト」系の説明では、コマンドの文頭に$をつけて表現されることが多いようです。
当記事でもそれに倣って記載しています。

実際にコマンドを入力するときは、git~以下をコピペしてください。
# コメント 補足事項など。
(対話モードでは使えません、、、)
<> 編集点(という表現で良いのかな…?) 任意の値(名前、識別子など)を入力してください。
(コミットの)識別子 コミットごとに付与される半角英数字7桁の番号。 SHA-1というハッシュ値だそうです。
当記事では<コミット>と表記します。

【1】ブランチのリストを出力して現在地を確認

その名もbranchコマンド。分かりやすい名前だ…

[a]ローカルリポジトリのみ表示

書き方

下記3件のコマンドは同じ結果が出力されます。

  • オプションなし(デフォルト)

    $ git branch
    

  • オプションつき

    $ git branch --list
    

  • オプションのショートハンドつき

    $ git branch -l
    

なお、これ以降、--list-lのようにオプション付きのものを2行続けて書いている場合は、「同じ意味のコマンド」を指しているものとします。

現在のブランチは、*アスタリスク)でハイライトされます。
bash等、使用するエディタによってはブランチ名に色も付きます。)

# 入力
$ git branch
 
# 結果
  branch1
* branch2
  master

[b]リモートリポジトリも含めて表示

書き方
$ git branch -a
$ git branch --all
# 入力
$ git branch -a
 
# 結果
  branch1
* branch2
  master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

【2】(旧)ブランチの切り替え

checkoutコマンドを使用します。
いったん現在のブランチから退出(チェックアウト)して、目的のブランチに移動するイメージなんですかね?

<2020/09/16追記>
Gitのバージョンアップにより、新しいコマンドが別途追加されました(後述)。

[a]既存のブランチへ切り替え

書き方
$ git checkout <目的のブランチ名>
# 入力
$ git checkout branch1
 
# 結果
Switched to branch 'branch1'

[b]ブランチを新規作成して切り替え

書き方

ブランチを作成することを「ブランチを切る」と呼ぶみたいです。かっこいい。

$ git checkout -b <目的のブランチ名>
# 新規作成して切り替え
$ git checkout -b branch3
 
# 結果
Switched to a new branch 'branch3'
 
# 切り替えできたか確認
$ git branch
 
# 結果
  branch1
  branch2
* branch3 # 現在のブランチに`*`がつく
  master

[c]現在の変更内容を破棄して強制的に切り替え

書き方

Gitが認識しないファイルで作業してしまった場合や、作業ツリーに変更があった場合などに使えます。

$ git checkout -f <目的のブランチ名>
$ git checkout --force <目的のブランチ名>
# 入力
$ git checkout -f branch1
 
# 結果
Switched to branch 'branch1'

【2】(ver. 2.23~)ブランチの切り替え

<2020/09/16追記>
この記事を投稿した後に、Gitのバージョンアップでcheckoutコマンドが下記2点に分離されました。

コマンド 役割
switch ブランチを移動する
restore コミット前の修正を取り消す

具体的でより使いやすいですね!

[a]既存のブランチへ切り替え

書き方
$ git switch <目的のブランチ名>

[b]ブランチを新規作成して切り替え

書き方
$ git switch -c <目的のブランチ名>
$ git switch --create <目的のブランチ名>

[c]現在の変更内容を破棄して強制的に切り替え

書き方
$ git switch -f <目的のブランチ名>
$ git switch --force <目的のブランチ名>
$ git switch --discard-changes <目的のブランチ名>

discardで「破棄する」という意味です。

このシリーズについて

Gitのコマンドについて、勉強しつつ記事にまとめています。

誤り、分かりづらい等ありましたら、ぜひコメント欄Twitterお問い合わせフォーム等でご教示ください!

次回

【Git勉強中】ステージに上げたり下げたり。 - ゆるおたノート

連載目次

  1. 【Git勉強中】操作に慣れてきたので、流れを整理してみました。 - ゆるおたノート
  2. 当記事【Git勉強中】ブランチの移動を使い分けたい - ゆるおたノート
  3. 【Git勉強中】ステージに上げたり下げたり。 - ゆるおたノート
  4. 【Git勉強中】ステージした変更を記録する - ゆるおたノート
  5. 【Git勉強中】あっ!そのコミット訂正させてください! - ゆるおたノート
  6. 【Git勉強中】自分のコミット履歴を提出する - ゆるおたノート
  7. 【Git勉強中】リポジトリの作成と接続 - ゆるおたノート

参照

【Git入門】チェックアウト(checkout)とは?使い方を基礎から解説! | 侍エンジニア塾ブログ(Samurai Blog) - プログラミング入門者向けサイト git コマンド branchの作り方 - Qiita

<2020/09/16追記>
Git - git-checkout Documentation Git - git-switch Documentation

【Git勉強中】操作に慣れてきたので、流れを整理してみました。

Gitって難しいですね。
最初はマウスでポチポチしていましたが、スニペットツール*1を駆使してコマンドを使う方がもうちょっと早く出来るかなと思い、ただいま練習中です。

少し操作に慣れてきたので、流れを整理してみました。

「はて、そもそもGitとは?」な方には、こちら↓の記事をオススメします!

非エンジニアのためのバージョン管理Git~メリットと導入前の準備

基本の流れ

【1】ローカルリポジトリを作成する

手順
  1. バージョン管理をしたいディレクトリ(=フォルダ)に移動する
  2. ディレクトリをGitに登録する
  3. (必要に応じて).gitignoreファイルや.gitignore_globalファイルを作成・編集しておく
詳しくは…

【Git勉強中】リポジトリの作成と接続 - ゆるおたノート

【2】作業スペースを準備する

手順
  1. ローカルリポジトリにあるブランチ(=作業場所)を確認する
  2. (目的のブランチがない場合)ブランチを新規作成する*2
  3. ブランチを切り替える
  4. (念のため)現在のブランチを確認する
詳しくは…

【Git勉強中】ブランチの移動を使い分けたい - ゆるおたノート

【3】コミットするファイルをまとめる

手順
  1. ファイルを編集する
  2. ステージングする
詳しくは…

【Git勉強中】ステージに上げたり下げたり。 - ゆるおたノート

【4】編集履歴を記録する

手順
  1. ここまでの編集履歴を確認する
  2. 内容に問題がなければ、コミット(=編集履歴を保存)する
  3. ローカルリポジトリmasterブランチ(=メインの作業場所)に移動する
  4. 編集履歴をマージ(=ここまでのデータを統合)して反映させる
詳しくは…

【Git勉強中】ステージした変更を記録する - ゆるおたノート 【Git勉強中】あっ!そのコミット訂正させてください! - ゆるおたノート

【5】リモートリポジトリを作成する

手順
  1. GitHub(もしくはBitBucket)でリポジトリを作成する
  2. ローカルリポジトリと接続する
詳しくは…

【Git勉強中】リポジトリの作成と接続 - ゆるおたノート

【6】履歴をリモートリポジトリに反映する

手順
  1. これまでのコミットを確認する
  2. リモートリポジトリにプッシュする
  3. 【2】と【4】を繰り返し
詳しくは…

【Git勉強中】自分のコミット履歴を提出する - ゆるおたノート

【7】(masterブランチ以外にpushしている場合)

手順
  1. コミット履歴に問題がなければ、リモートリポジトリでもmasterブランチにマージする
詳しくは…

【Git勉強中】自分のコミット履歴を提出する - ゆるおたノート

ちなみに…

補足

リポジトリの作成順

リモートリポジトリは、先に作成しても大丈夫です。

ただし、どちらを先に作るかによって、リポジトリを接続するコマンドが変わります。
覚えるのがちょっとめんどくさいですね…

おすすめ記事

各コマンドや用語の解説は、下記2社のページがとても分かりやすかったです。

ブランチの使い方

ローカルリポジトリで編集するときにブランチを切るのは、事故防止のため「原則master以外のブランチで作業しよう」というGitの基本方針だそうです。

最近までそれを知らなくて、masterブランチで作業していました(キケン!)。

詳しくは、下記記事の「ブランチとは」~「リモート追跡ブランチとは」あたりが参考になりました。
https://qiita.com/kyoyyy/items/161b6905f45bee2efe21

<2020/08/26追記>
その後、当該記事にはアクセスできなくなってしまったようです。。。残念。。。

疑問

ナントカ認証

ローカルリポジトリとリモートリポジトリの接続には、3種類の認証方法があります。

  1. OAuth認証
  2. https認証
  3. SSH認証

GitHubOAuth認証を推奨しているようですが、SSH認証の方が安全という記事もあって…
どれが安全なんだろうな…?(詳しい方、ぜひ教えて下さい🙏)

このシリーズについて

Gitのコマンドについて、勉強しつつ記事にまとめています。

誤り、分かりづらい等ありましたら、ぜひコメント欄Twitterお問い合わせフォーム等でご教示ください!

次回

【Git勉強中】ブランチの移動を使い分けたい - ゆるおたノート

連載目次

  1. 当記事【Git勉強中】操作に慣れてきたので、流れを整理してみました。 - ゆるおたノート
  2. 【Git勉強中】ブランチの移動を使い分けたい - ゆるおたノート
  3. 【Git勉強中】ステージに上げたり下げたり。 - ゆるおたノート
  4. 【Git勉強中】ステージした変更を記録する - ゆるおたノート
  5. 【Git勉強中】あっ!そのコミット訂正させてください! - ゆるおたノート
  6. 【Git勉強中】自分のコミット履歴を提出する - ゆるおたノート
  7. 【Git勉強中】リポジトリの作成と接続 - ゆるおたノート

注釈

*1:最近PhraseExpressを入れてみました。

*2:ブランチの作成を「ブランチを切る」と呼ぶみたいです。かっこいい。

このブログ、リニューアルしました。

また少し更新が止まってしまってごめんなさい。
近頃はちょこっとずつ勉強をしていました。

その間に色々と考えた結果、このブログをリニューアルすることにいたしました。

変えること

このブログは学習の記録に特化します。

当初は「なんでも書く」つもりで始めたブログですが、記事が増えてくるとともに雑多感が増して個人的に少し使いづらかったので、内容によってブログを分けることにしました。

音楽・雑記系の記事は別ブログ化して、こちらは学習の記録に特化することとします。
今後は説明系よりメモ的な内容が増える予定です*1

ちょっと収益化を目指します。

SEOとかちんぷんかんぷんですが、私の文章力でどのくらい貰えるのか試してみたいのもあり…
まずは有料化の費用を少しでも回収出来たらいいな…

自分がパンクしない程度に頑張ってみたいと思います。
ダメになったら是非鼻で笑って下さい!笑

変わったこと

ブログURLを変更しました。

たぶん読者のみなさんにとって1番大事なことですね!

上記2点に関連して、独自ドメインを取得しURLも変更しました。

もしブックマークやRSS等ご登録いただいていた方がいらっしゃったら、お手数をおかけしますが、設定を修正いただければと思います。

なお、「読者」登録や「はてブ」の記録は自動で移行する模様*2なので、ご安心ください。

help.hatenablog.com

大事なページを増やしました。

Googleアドセンスの申請にあたり、「プライバシーポリシー」と「お問い合わせフォーム」を追加してみました。

help.hatenablog.com

※お問い合わせフォームも、追々このブログに合わせて修正したいと思っています。
このブログでお問い合わせが来るのか謎ですが…

また、調べていて気づいたのですが、Google AnalyticsAmazonアフィリエイトも「プライバシーポリシー」の掲載が必要だったようですね…
「知らなかった」では済まされない気もしますが…皆様申し訳ありません…

こちらも合わせてアップしました。

やりたいこと

ブログのデザイン・テーマ

まだ間に合っていませんが、どこかのタイミングで変更したいなと思っています。

音楽・雑記系記事の移転

こちらもまだ間に合っていませんが、少しずつ移転します。

Search Consoleにお知らせ

これは「やりたい」というより「マスト」な気がしますが、過去のURLをGoogleさんのインデックスから外してもらわねば…めんどくさい…

続けること

連載途中の記事

今まで連載していた系の記事で、途中のものは今後も少しずつ更新します。
たぶん時系列バラバラになりそうですが、生暖かく見守っていただけると幸いです。

専門用語は減らす

悪い意味で最近少し慣れてきている気がしますが、出来るだけ専門用語は使わないようにすることと、もし使うなら出来る範囲で噛み砕いて書きます。

最低限、自分の脳みそがリセットされても読み返せば理解できるレベルには…!

よろしくお願いいたします。

1年以上使ったドメインを変更するのは結構な賭けだと思いますが、細々とやっていけたらと思います。

今後とも、どうぞよろしくお願いいたします。

*1:私の語彙だと、どうしても上から目線になってしまって自分でも気持ち悪くて…

*2:記事間のリンクも勝手に修正されているみたいです。助かった…!

オブジェクト指向って、なんだ?

数ヶ月掛けてちょこっとずつ、読み進めている本(後述)がありまして、その中でオブジェクト指向について説明があります。

正直まだ「ちょっと何言ってるかよく分からない」状態の部分だらけではあるのですが、現時点で本を読んで分かっていること・私の解釈を、整理しながらここに記録しておくことにします。

オブジェクト指向とは?

手続き型プログラミングと、その問題

現代のプログラム界では、以下3つのパラダイム(スタイル、手法)がある。


  1. 手続き型プログラミング
  2. 関数型プログラミング
  3. オブジェクト指向プログラミング

手続き型プログラミングは、「アレをやって、次はコレをやって…」という連続した手続きを行うことで、順番にほしい結果に導く。
これはこれで、小さいプログラムには有効な手段。

しかし、手続き型プログラミングには「グローバル」なスコープ*1の問題がある

大きいプログラムになると、「複数の手続き(≒関数)にまたがって同じデータを扱う」必要が出てくることがあり、そんな時にグローバルな変数は役に立つ。

ところが、機能を追加するにつれてプログラムが複雑化し、グローバル変数も増える。
やがて、いくつもの関数がグローバル変数を読み書きするようになると、変数のコントロールが難しくなっていく。

一方ではインクリメントに使っているのに、他方ではデクリメントに使っていたりなど、1つのグローバル変数に対し複数の関数が操作することで、制作者の意図しない動作が発生してしまったりする。

このように、手続き型プログラミングでは、グローバルな変数の扱いが難しくなることがある。

グローバル変数の多用を避けることでエラーを減らすことも出来るが、関数型プログラミング」や「オブジェクト指向プログラミング」では、「処理や変数をローカルに閉じ込める」アプローチを取ることで、この問題の解決を目指す。

今回は、後者の「オブジェクト指向プログラミング」を扱う。

オブジェクト指向の目的

オブジェクト指向プログラミング」は、「オブジェクト」に状態(=変数の値)を持たせることで、グローバルなステートメントを排除する*2

「状態」はオブジェクトの内部で操作することにして、オブジェクトの外(メインの処理など)からは操作させない。

コレを基本とする。

これによるメリット・デメリットは、本書より引用する。

オブジェクト指向プログラミングの利点は、コードの再利用が促進されて、開発や保守にかかるトータルの時間が短縮されることです。さらに、解決したい問題を分割して扱うことが推奨されるため、保守しやすいコードになります。オブジェクト指向プログラミングの欠点は、プログラムを書く前の計画や設計などに、より多くの労力をかける必要があることです。

出典:http://a.co/1sj1P6I


将来的に効率化出来る代わりに、前もってじっくりしっかり設計しておく必要がある、と。

オブジェクトは「クラス」で表現する

「オブジェクト」について定義・分類する仕組みのことを「クラス」、クラスを呼び出す側のプログラムを「クライアント」と呼ぶ。

共通した特徴(=属性、プロパティ)を、クラスを使って定義し、属性の値の違いで個々のインスタンス、すなわちオブジェクトを作成する。

また、クラスの内部で定義し、そのクラスから生成したオブジェクトを通して呼び出す関数(のようなもの)は「メソッド」という。

メソッドは関数とほとんど同じ構文で定義するが、関数とは2つの違いがある。


  • クラスのスイート部分に定義すること
class [クラス名]:
    [スイート] # ← ここ
[クラス名].prototype.メソッド名 = function() {
  // ここ
}
'クラスモジュール(オブジェクト名に[クラス名]を設定する)
Public Sub メソッド名()
    ' ここ
End Sub


  • (特別な場合を除いて)引数を少なくとも1つ(※)定義すること
    Pythonの場合はselfJavaScriptならthisVBAならMe
    それぞれ自動で渡されるので、引数として明示的に書く必要は無い。
class [クラス名]:
    def メソッド名(self)
        処理
[クラス名].prototype.メソッド名 = function(this) {
  処理
}
'クラスモジュール(オブジェクト名に[クラス名]を設定する)
Public Sub メソッド名(Me)
    処理
End Sub

オブジェクト指向の4大要素

オブジェクト指向は、下記4つの要素から成り立っている。


  1. カプセル化
  2. 抽象化
  3. ポリモーフィズム多態性
  4. 継承

PythonJavaRubyのように、これらの4大要素すべてを提供してこそ*3オブジェクト指向プログラミング言語と言えます。

出典:http://a.co/g77Ar66


…ふ、ふむふむ。何やら聞いたことない熟語や横文字が…

続きは、また次回。

参考文献

注釈

*1: VBAのスコープについては、手前味噌ですがこちらをご参照下さい。 yuru-wota.hateblo.jp

*2: 関数型では、「引数」として状態を「関数」に渡して処理する。
次の関数に渡して処理、その次の関数に渡して処理、…これを繰り返すことでほしい結果に導く。

難易度が高いらしいですね…?

*3: VBAも、頑張れば出来ないことはないようだけど、このあたりが「モダンな言語」プログラマーから距離を置かれる要因なのかな。

【PC設定】NumLockとInsertを消してみる - 「Change Key」で遊ぶ

前回入れた「Change Key」
【PC設定】NumLockとInsertを消してみる - 「Change Key」をインストールする - ゆるおたノート

こちらで、実際にNumLock/Insert問題に立ち向かってみます!

まえがき

このソフトの使用には、「管理者権限」が必要になります。
それ以外のアカウントでは反映されないので、あらかじめご留意ください。

また、本記事でご紹介しているのは「レジストリの変更」を行うソフトです。
いわゆる「PCのシステム部分」をいじるものなので、操作は慎重に行いましょう。
共有PCの場合は、管理者や他に使う方々の許可も得てから行うようにしてください。

設定を変えてみる(Yさんの場合)

現状を確認する

当記事公開時点で、HP製ノートPC(Pavilion 15-CS0020TU)のキーボードをそのまま使っています。

HP製ノートPC(Pavilion 15-CS0020TU)のキーボード

いま困っているのは下記の3点です。

  • テンキーの左上、BackSpaceの隣にNumLockがあって、いつの間にか数字入力が不可に…

  • テンキーの0Insertも割り当てられていて、十字キーを操作中に挿入モードに…

  • Applicationキーが無いので、右クリックの代わりが出来ない…*1

設定を変更する

設定内容(お試し中)

上記3点を解決すべく、下記のように変更してみました。

  • 変更前 - 初期設定(再掲
    初期設定のスクリーンショット

  • 変更後
    ※分かりやすいように、変えたところを強調しています。
    変えたところは後述します。

    • NumLockキーにDeleteキーを割り当てて、左方向に消すBackSpaceと右方向に消すDeleteを両隣に。

    • Insertキーは、普段使わないし十字キー使用中に小指が触れやすい位置なので、無効化。

    • CapsLockキーも、ほとんど使わないけど定数名とかで使いそうなので、とりあえず半角/全角キーの位置に移動*2

    • CtrlキーやShiftキーは「左手で同時押し」系のショートカットが多いので、1つずつ上にして他のキーに近づけてみる。

    • 空いた左Ctrlキーの位置にApplicationキーを割り当て。

3日使ってみた感想
  • 無意識NumLock/Insert問題はめでたく解消しました!やったー!

  • 左Shift左Ctrlは非常によく使うキーですが、3日では全く慣れないので誤タッチ頻発してます…

後者はそのうち慣れるような気もしますが概ね満足しています。

もうちょっと試してダメそうだったら、誤タッチ部分は元に戻して、元CapsLockのところにApplicationキーの方が使いやすいかもしれません。
でも、右クリックも危ないアクションが多いので、触れやすいところには置きたくないジレンマが…悩む…

設定を保存する

まだ悩むところはありますが、キリがないのでとりあえずこの設定で決定します。

保存する

ファイル+現在のキー内容を名前をつけて保存します(W)の順に選択します。

「ファイル」→「現在のキー内容を名前をつけて保存します(W)」の順に選択

名前をつける

全角10字までだそうです。結構厳しい…
ファイル名は半角20文字、全角10文字まで。

日付は後で見られるのですが、キー情報を1日にいくつか作成・比較することを想定して、とりあえず「時刻」と「どこを変えたか」を簡単につけておくことにします。

1853_Appliを下にした

無理やり感がすごい(笑)
まぁ、後で分かれば良いので…

スクショを撮る

保存ができたら、前回と同じように現在の設定内容でスクリーンショットを撮っておきます。
現在のスクリーンショット

名前をつける

こちらのファイル名は(パスを含めて)255文字までなので、こちらで「どこを変えたか」を具体的に記録しておくことにします。
私は「日付」、「時刻」、「どこをどう変えたか?」の順にしました。

20190523_1853_アプリケーションキーを左下にして、CtrlとShiftを上に移動.PNG

ここの日付と時刻を設定データの名前と同じにして、後で参照しやすいようにしておくと良いでしょう。
※前回保存した「初期画面」と日付が前後しているのは大人の事情なのでご了承を…

設定を反映させる

それでは、レジストリの変更を実行してみましょう。

登録+現在の設定内容で登録します(R)の順に選択します。
「登録」→「現在の設定内容で登録します(R)」の順に選択

再起動を促されるので、問題がなければOKを押して再起動します。
「OK」を押して再起動

完了!

再起動後、設定が反映されていれば、これで完了です!

エディタなどでカチャカチャ試してみて下さい!

後記

お疲れ様でした!

他にもいくつか設定データを残すことが出来るので、何パターンか保存だけしておいて、試しながら検討することも出来ます。
私もまだ完全には満足できていないので、少しずつ試していきたいと思います。

それでは、みなさんも良きPCライフを!

公式HP(開発者様)

最後に、この度お世話になったソフトの開発者様の公式HPを再びご紹介します。

Satoshi村

ありがとうございます。
これからもご活躍をお祈りしております😌

このシリーズについて

フリーソフトChange Key」の使い方についてまとめています。

誤り、分かりづらい等ありましたら、ぜひコメント欄やTwitterお問い合わせフォーム等でご教示ください。

連載目次

  1. 【PC設定】NumLockとInsertを消してみる - 解凍ソフト「LhaPlus」の準備編 - ゆるおたノート
  2. 【PC設定】NumLockとInsertを消してみる - 「Change Key」をインストールする - ゆるおたノート
  3. 当記事【PC設定】NumLockとInsertを消してみる - 「Change Key」で遊ぶ - ゆるおたノート

注釈

*1:Excel等で結構多用しているのです…

*2:IMEの設定で、変換・無変換キーにIME-ON/OFFを割り当てています。

【PC設定】NumLockとInsertを消してみる - 「Change Key」をインストールする

昨日、解凍ソフトの準備を行いました。
【PC設定】NumLockとInsertを消してみる - 解凍ソフト「LhaPlus」の準備編 - ゆるおたノート

今回は、早速「Change Key」を入れてみます。

まえがき

このソフトの使用には、「管理者権限」が必要になります。
それ以外のアカウントでは反映されないので、あらかじめご留意ください。

また、本記事でご紹介しているのはレジストリの変更」を行うソフトです。
いわゆる「PCのシステム部分」をいじるものなので、操作は慎重に行いましょう。
共有PCの場合は、管理者や他に使う方々の許可も得てから行うようにしてください。

「Change Key」をダウンロードする

それでは、こちら↓から、端末のお好きなところにダウンロードしてください。

「Change Key」非常駐型でフリーのキー配置変更ソフト - 窓の杜

開発者様の公式HP(後述)もありますので、そちらからでも良いでしょう。

解凍する

開いてみる

ダウンロードが完了したら、ダブルクリックで開いて下さい。
「ChgKey15.LZH」というファイルをダブルクリック

解凍先の指定

昨日の「アーカイブ先を選択する」を選択した方は、ここでこんな画面が出ます。
「アーカイブ先」を選択する画面

解凍先を変更する場合

解凍先(解凍ファイルの保存先)を変えたい場合は、右側のをクリックして選択しましょう。
右側の[…]をクリック

好きな解凍先を選びます。
解凍先を選択

解凍完了

解凍が完了したら、自動で解凍先が開きます。
エクスプローラーで解凍先が開く

ちなみに、「ChgKey15.LZH」と同じフォルダに解凍した場合、元のフォルダではこのように「圧縮ファイルと同じ階層に並んでいる」状態のはずです。
解凍したファイルが圧縮ファイルと同じ階層に並んでいる

使い方をメモしておく

このソフトは、ちゃんと使うには「管理者として実行」する必要があります。

次回使いたい時に忘れないよう、そのことをメモっておきましょう。

「テキストファイル」を新規作成する

該当フォルダのエクスプローラー画面で、空いているところを右クリックしてください。

新規作成(X)のあたりにカーソルを当てて1~2秒ほど待つと、また選択肢が増えます。
この中のテキスト ドキュメントを選択します。
「テキストドキュメント」を新規作成する

いま作成したファイルの中に文章でメモしても良いのですが、私はこれを開くのすら面倒なので(笑)、ファイル名に直接メモしちゃいます。

私はこのようにメモってみました。

▼「管理者として実行」すること!

エクスプローラーでは、こんな感じになります。
ファイル名に使い方をメモしておく

1文字目を記号にすると「ファイル名順」でソートした時に自動で1番上に来るので、大事なファイルを見つけやすくしたいときにはオススメです*1

高DPI設定の変更

さて、高解像度のPCをお使いの方は、ここで前回と同じようにディスプレイの設定を変更しておいて下さい。

【PC設定】NumLockとInsertを消してみる - 解凍ソフト「LhaPlus」の準備編 - ゆるおたノート

そのままでも使うことは出来るのですが、メニューバーで文字がぼやけちゃうとせっかくの良いPCがもったいないので…!

「Change Key」を起動

「管理者として実行」する

それでは、ここまで準備ができたら、いよいよソフトを起動します。

ファイル名「ChgKey.exe」のあたりで右クリックして…
※名前がちょっと省略されていますが、普通に使えるのでご安心を!

ファイル名のあたりで右クリック

「管理者として実行」を選択して下さい。
「管理者として実行」する

このあとで、「不明な発行元からのアプリがデバイスに変更を~」といったメッセージが出てきたら、はいで大丈夫です。

初期画面

起動できたら、こんな感じでキーボード風の画面が出ると思います。
「Change Key」の初期画面

何のキーがラインナップされているか、ザッと確認しておきましょう。

キーボードの設定をいじる

触ってみる

試しに、この画面上でNumLockをクリックしてみて下さい。
※この時点では、まだ「設定データが作成されるだけ」でキーの変更は行われませんので、いくつかいじってみても大丈夫です。
画面上で「NumLock」キーをクリック

すると、背景が緑っぽい画面に変わります。
背景が緑に変わる

画像だと分かりづらいかもしれませんが、青枠でNumLockキーが選択された状態になります。
タイトルバーにも「【NumLock】キーをどのキーに変更しますか?」と書かれていますね。

ここで変更後のキーをクリックすると、元の画面に戻ります。

変えてみる

試しにDeleteキーを選択してみます。
「Delete」キーを選択

変更後

元の画面に戻りました。
元の画面に戻る

これも画像では分かりづらいかもしれませんが、NumLockキーだったところがDeleteキーに表示が変わりました。

こんな要領で、「どのキーにどのキーを割り当てるか?*2」を1つずつ変更して、設定データを作成していきます。
もちろん、無効にすることも出来ます。

初期設定を記録しておく

さて、この後は段々どこをどう変えたか分からなくなると困ると思うので、今のうちに初期設定を記録しておきましょう。

もとに戻す

さっき色々変更した方は、元に戻しておいてください。

まだ実行はしていないので、メニューバーからリセット > すべてのキーを初期状態にします の順に選択するだけでOKです。
メニューバーから「リセット」を選択
「すべてのキーを初期状態にします」を選択

スクリーンショット

準備ができたら、現在の状態をスクリーンショットとして撮影しておきます。

Ctrl+Print Screenしてペイントに貼り付けて保存でも良いのですが、せっかくなのでスクショソフトの使い方も覚えちゃいましょう。

Snipping Tool

Windows7~10なら、「Snipping Tool」というスクショソフトが標準装備されています。
スタートメニュー等から探すか、コルタナさんに聞いてみて下さい。

撮影する

新規作成を押して画面が白っぽくなったら、マウス等で切り取りたい範囲を選択し、保存しましょう。
※これだけは画像で説明するのがちょっと難しいので…動画でどうぞ*3
Snipping Toolでスクリーンショットをサクッと作成する

スクショのファイル名

今回のスクショ画像は、以下の名前で保存しました。

20190524_1910_初期画面.PNG

「日付、時刻、何の画面か」で名前をつけました。
次回、これをもとに新しい設定をするので、なんとなく覚えておいて下さい。

後記

ここまでで、キーをいじる準備が整いました。
あまり難しい操作が無かったとは思いますが、そうは言っても、システムをいじるのはちょっと怖いですよね。

次回は、実際に「レジストリの変更を実行」します。
ドキドキですが、こまめに記録しつつ保存しつつで、慎重に慎重に対応していきます。

公式HP(開発者様)

最後に、この度お世話になったソフトの開発者様の公式HPを記載させていただきます。

Satoshi村

ソフトが気に入った方は、他のソフトも眺めて見ると良い出会いがあるかもしれません。

このシリーズについて

フリーソフトChange Key」の使い方についてまとめています。

誤り、分かりづらい等ありましたら、ぜひコメント欄やTwitterお問い合わせフォーム等でご教示ください。

次回

【PC設定】NumLockとInsertを消してみる - 「Change Key」で遊ぶ - ゆるおたノート

連載目次

  1. 【PC設定】NumLockとInsertを消してみる - 解凍ソフト「LhaPlus」の準備編 - ゆるおたノート
  2. 当記事【PC設定】NumLockとInsertを消してみる - 「Change Key」をインストールする - ゆるおたノート
  3. 【PC設定】NumLockとInsertを消してみる - 「Change Key」で遊ぶ - ゆるおたノート

注釈

*1:乱用にはお気をつけ下さい!
「※大事なファイル」、「※これが最新_大事なファイル(コピー)」、「※大事なファイル-その2」、「※大事なファイル(コピーコピー)」、みたいなことにはならぬよう…

*2:いわゆるキーバインドです。

*3:今回の動画↑は「Screenpresso」というフリーソフトを使っています。
ウィンドウまるごとスクショも可能で便利です。

マニュアルをよく作るとかでスクショを大量に撮る方は、こちらもご検討されると良いかと思います。
端末や所属組織の制限に合わせてご選択を…!