MW211 EXIT

devlog
設計/排他制御
2014年09月09日
ロック(排他制御)には以下の種類がある
  ①参照用共有ロック
  ②更新用共有ロック(楽観的ロック)
  ③更新用占有ロック(悲観的ロック)

参照の場合、他に影響を与えないから基本的にロックの必要はない。
但し、他が更新中の場合は、そちらを優先させなきゃならないので
その手続きとして「共有ロック」を行う。
「共有ロック」は、「共有ロック」同士(同時に参照のみ)なら排他なし、
他方が「占有ロック」ならその完了を待つことになる。
(逆に「占有ロック」しようという方は、本「共有ロック」の解除を待つ必要がある)
だから「共有ロック」とは、「ロック」とはいうものの実際には「ロック」はせず
他ロックのお伺いを立てる手続きのことといえる。

更新の場合、他に影響が大なので、占有する必要がある。
ということで、「占有ロック」を行う。
「占有ロック」は、「占有ロック」だろうが「共有ロック」だろうが
他でロックをしている場合はその完了を待たねばならない一方、
自分がロックしている間は他が待ちとなる強力なロックだ。
(後述の「楽観的ロック」との対比から「悲観的ロック」とも言われる)

ところで、更新の場合にもう少し穏便にロックできないものかという考えがある。
大々的に「占有ロック」をすると他から苦情が来るので
「占有ロック」なんかしないで、こっそり更新してしまいたいという場合だ。
そもそもなんでロックが必要かというと更新する対象を一旦参照するけど
それが更新前に誰かに変更されるとおかしくなっちゃうので、
その期間をまるごと占有しなければならないからだ。
だったら、更新時に誰かに変更されていたのをみつけたら
やり直してしまえばロックする必要がないじゃんというのが、
「楽観的ロック」の発想。
自分の優先度を下げる控えめなロックなため、他が他がと更新されまくると
なかなか更新できないという欠点は持つけれど。
一応、参照時には他の参照と同様に「共有ロック」はかけるので
「共有ロック」の分類に属する。
但し、更新処理時(最後の一瞬)は、さすがに排他制御かけなきゃなんないので
実際は「排他ロック」を行っている。
(但し、割合が低いので「共有ロック」が前面に出る感じ)
分類:設計
ExcelVBA/UTF-8変換
2014年09月08日
シフトJISファイルを読み込んでUTF-8に変換し上書する関数。
┌──────────────────────────────────────┐
│Public Sub UTF8変換(対象ファイル名 As String)                               │
│    Dim 変換前 As New ADODB.Stream                                          │
│    Dim 変換後 As New ADODB.Stream                                          │
│                                                                            │
│    Set 変換前 = CreateObject("ADODB.Stream")                               │
│    Set 変換後 = CreateObject("ADODB.Stream")                               │
│    変換前.Charset = "Shift_JIS"                                            │
│    変換後.Charset = "UTF-8"                                                │
│    Call 変換前.Open                                                        │
│    Call 変換後.Open                                                        │
│                                                                            │
│    Call 変換前.LoadFromFile(対象ファイル名)                                │
│    Call 変換前.CopyTo(変換後)                                              │
│    Call 変換後.SaveToFile(対象ファイル名, adSaveCreateOverWrite)           │
│                                                                            │
│    Call 変換後.Close                                                       │
│    Call 変換前.Close                                                       │
│    Set 変換後 = Nothing                                                    │
│    Set 変換前 = Nothing                                                    │
│End Sub                                                                     │
└──────────────────────────────────────┘

なお、ExcelVBAエディタ上から「ツール」→「参照設定」を開き、
「☑Microsoft ActiveX Data Objects 6.1 Library」とチェックを入れる必要あり。
分類:ExcelVBA
Excel/入力規則のリストの設定
2014年09月07日
Q.文字サイズを変更したい
A.入力規則のリストの文字サイズについては、セル単位の設定ではなく
    Excel全体としての設定となるため、個別に変更は無理。
    もし変更するなら、Windowsのレジストリをいじることになる。
    但し、Excelシートの表示倍率(ズーム)の影響を受けるので
    表示倍率を小さくしない限り問題はないはず。

Q.横幅を変更する
A.セルの横幅に比例するので、セルの横幅を広げる(もしくは狭める)しか手段はない。
分類:Excel
ExcelVBA/リスト入力の設定
2014年09月06日
以下のような感じ。
┌──────────────────────────────────────┐
│With Selection.Validation                                                   │
│    .Delete                                                     ─初期化    │
│    .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _              │
│        Formula1:="1:織田信長,2:豊臣秀吉,3:徳川家康"            ─リスト内容│
│    .InCellDropdown = True                                      ─リスト    │
│    .IgnoreBlank = True                                         ─空欄許容  │
│    .ShowInput = True                                           ┐          │
│    .InputTitle = "コード入力"                                  │ガイド情報│
│    .InputMessage = "コードを入力してください"                  ┘          │
│    .ShowError = True                                           ┐          │
│    .ErrorTitle = "エラー"                                      │エラー情報│
│    .ErrorMessage = "選択肢中の内容のみ入力できます"            ┘          │
│End With                                                                    │
└──────────────────────────────────────┘
リスト内容はカンマ区切りとなる。

以下の指定により、完全に入力を限定的にできるか否かを決められる。
┌──────────────────┬───────────────────┐
│AlertStyle:=xlValidAlertStop        │停止(決められた内容しか入力できない)  │  
├──────────────────┼───────────────────┤
│AlertStyle:=xlValidAlertWarning     │注意(他も入力できる)                  │
├──────────────────┼───────────────────┤
│AlertStyle:=xlValidAlertInformation │情報(他も入力できる)                  │
└──────────────────┴───────────────────┘
分類:ExcelVBA
ExcelVBA/シートの指定
2014年09月04日
セルは以下の階層で指定する。
┌──────────────────────────────────────┐
│ブック.シート.セル                                                          │
└──────────────────────────────────────┘
ここでは「ブック.シート」階層についてまとめた。

以下のようにも指定できるが、それは上記の省略形である(詳細は後述)。
┌──────────────────────────────────────┐
│セル                                                                        │
│シート.セル                                                                 │
└──────────────────────────────────────┘

ブックの指定手段は以下の通り。
┌────────────────┬─────────────────────┐
│ThisWorkbook.シート.セル        │マクロのあるブック                        │
│ActiveWorkbook.シート.セル      │アクティブなブック                        │
└────────────────┴─────────────────────┘

シートの指定手段は以下の通り。
┌────────────────┬─────────────────────┐
│ブック.ActiveSheet.セル         │アクティブなシート                        │
│ブック.Worksheets(シート名).セル│シート名指定によるシート                  │
└────────────────┴─────────────────────┘
「Worksheets(シート名)」は「Sheets(シート名)」でもOKだが、
(グラフ等を除く)純粋なワークシートとしては「Worksheets(シート名)」指定が厳密的。

ブックの指定は、マクロの書いているブックに絞り込んだ方が安全。
┌─────────────────────┬────────────────┐
│○ThisWorkbook.ActiveSheet.セル           │                                │
│△ActiveWorkbook.ActiveSheet.セル         │完全に動的な指定                │
│○ThisWorkbook.Worksheets(シート名).セル  │完全に静的な指定                │
│△ActiveWorkbook.Worksheets(シート名).セル│                                │
└─────────────────────┴────────────────┘
できるだけ静的な指定とすると想定外のミスを減らせる。

そして、お待ちかねの省略形の実態。
┌─────────────┐  ┌──────────────────────┐
│セル                      │=│ActiveWorkbook.ActiveSheet.セル             │
├─────────────┤  ├──────────────────────┤
│Worksheets(シート名).セル │=│ActiveWorkbook.Worksheets(シート名).セル    │
└─────────────┘  └──────────────────────┘
つまり動的な指定のオンパレードなのだ。

ということで、省略形は一時的なプログラムではいいとしても
本格的なプログラムでは避けた方がいいだろう。
分類:ExcelVBA
ExcelVBA/誤入力防止の補助
2014年09月02日
「Cells(2, 3)」の入力値が、半角かつ大文字と限定されている場合に、
誤入力を防ぐため全角および小文字を変換するイベントは以下のような感じになる。
┌──────────────────────────────────────┐
│Private Sub Worksheet_Change(ByVal Target As Range)                         │
│    If Target.Row = 2 And Target.Column = 3 Then                            │
│        Application.EnableEvents = False                                    │
│        Target.Value = StrConv(Target.Value, vbUpperCase Or vbNarrow)       │
│        Application.EnableEvents = True                                     │
│    End If                                                                  │
│End Sub                                                                     │
└──────────────────────────────────────┘
分類:ExcelVBA
ExcelVBA/入力補助のはずが無限ループ
2014年09月01日
シート記述するマクロで、以下のように記述すると
「Cells(2, 3)」に値を入力した場合、自動で「様」がついてくれる想定だ。
┌──────────────────────────────────────┐
│Private Sub Worksheet_Change(ByVal Target As Range)                         │
│    If Target.Row = 2 And Target.Column = 3 Then                            │
│        Target.Value = Target.Value & "様"                                  │
│    End If                                                                  │
│End Sub                                                                     │
└──────────────────────────────────────┘
でも実際に実行してみると、入力後「様様様…」という、大量の「様」がついてしまう。

これは、自分で自分の値を変えてその結果新たに自分を呼び出しているから
…つまり無限ループしてるって訳だ。

ということで、これを防ぐ方法。
┌──────────────────────────────────────┐
│Private Sub Worksheet_Change(ByVal Target As Range)                         │
│    If Target.Row = 2 And Target.Column = 3 Then                            │
│        Application.EnableEvents = False                                    │
│        Target.Value = Target.Value & "様"                                  │
│        Application.EnableEvents = True                                     │
│    End If                                                                  │
│End Sub                                                                     │
└──────────────────────────────────────┘
「Application.EnableEvents = False」で一旦自分が呼ばれないようにしてから
値を変えればいいってことだ。
もちろん、次のイベントのために、「True」で戻すことも忘れずに。
分類:ExcelVBA
ExcelVBA/MSSQLのトランザクション処理
2014年08月31日
下記のような流れとなる。
┌──────────────────────────────────────┐
│    Dim データベース As New ADODB.Connection                                │
│    Dim テーブル As New ADODB.Recordset                                     │
│    ────────────────────────────────────│
│    ' トランザクション開始                                                  │
│    データベース.connectionString = (省略)                                  │
│    データベース.Open                                                       │
│    On Error GoTo トランザクション中にエラー発生                            │
│    データベース.BeginTrans                                                 │
│    ────────────────────────────────────│
│    ' テーブル更新                                                          │
│    テーブル.ActiveConnection = データベース                                │
│    テーブル.Source = "テーブル名"                                          │
│    テーブル.CursorType = adOpenKeyset                                      │
│    テーブル.LockType = adLockOptimistic                                    │
│    テーブル.Open                                                           │
│    テーブル.Filter = "[キー]='" & キー                                     │
│    テーブル.Fields("更新項目").Value = 値                                  │
│    テーブル.Update                                                         │
│    テーブル.Close                                                          │
│    ────────────────────────────────────│
│    ' トランザクション完了                                                  │
│    データベース.CommitTrans                                                │
│    データベース.Close                                                      │
│    Set テーブル = Nothing                                                  │
│    Set データベース = Nothing                                              │
│    Exit Sub                                                                │
├──────────────────────────────────────┤
│トランザクション中にエラー発生:                                             │
│    ' ロールバック                                                          │
│    MsgBox "エラー発生!"                                                   │
│    データベース.RollbackTrans                                              │
│    データベース.Close                                                      │
│    Set テーブル = Nothing                                                  │
│    Set データベース = Nothing                                              │
└──────────────────────────────────────┘
自前でトランザクションのSQL文を発行するよりも
用意されているメソッドに従ってやった方がいいようだ。
(SQL文発行だとうまく行かなかった)
分類:ExcelVBA
SQL/二階層以上先のLEFT JOIN
2014年08月25日
あまりないかもしれないが、直上にはないけど、そのまた上にある列と
「LEFT JOIN」したい場合、普通に以下のように書いたらNGだ。
┌──────────────────────────────────────┐
│SELECT *                                                                    │
│   FROM 親                                                                  │
│       LEFT 子                                                              │
│         ON 子.列A = 親.列A                                                 │
│           LEFT 孫                                                          │
│             ON  孫.列B = 親.列B                  ←×                      │
│             AND 孫.列C = 子.列C;                                           │
└──────────────────────────────────────┘

こんな時は、一旦上の階層でテーブルを完結させて、列が揃った時点で
そこに「LEFT JOIN」すればよい。
┌──────────────────────────────────────┐
│SELECT *                                                                    │
│   FROM (SELECT *                                                           │
│             FROM 親                                                        │
│                 LEFT 子                                                    │
│                   ON 子.列A = 親.列A) AS 親たち                            │
│       LEFT 孫                                                              │
│         ON  孫.列B = 親たち.列B                  ←○                      │
│         AND 孫.列C = 親たち.列C;                                           │
└──────────────────────────────────────┘
VIEWとかを駆使すれば見やすくなる。

ちなみに結合するキーの関係を図示すると以下のような変化が起こったってことだ。
┌─────┐  ┌─────┐
│親  子  孫│→│親たち  孫│
│●=●  ○│  │●      ○│
│●  ○  ●│  │●===●│
│○  ●=●│  │●===●│
└─────┘  └─────┘
分類:SQL
ExcelVBA/ボタンのセル座標
2014年08月23日
押されたボタンのセルにおける座標を求める方法。

ボタン左上が属すセルのX座標とY座標は以下の通り。
x = ActiveSheet.Shapes(Application.Caller).TopLeftCell.Column
y = ActiveSheet.Shapes(Application.Caller).TopLeftCell.Row

ボタン右下が属すセルのX座標とY座標は以下の通り。
x = ActiveSheet.Shapes(Application.Caller).BottomRightCell.Column
y = ActiveSheet.Shapes(Application.Caller).BottomRightCell.Row

残念ながら、左下(BottomLeft)と右上(TopRight)はないようだ。
分類:ExcelVBA
前へ 1 … 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 … 156 次へ