VBA フィルタを操作する

複数の人が操作(読み書き)をするようなファイルをVBAを使うとフィルタがかけられて思わぬエラーに遭遇したり書き込み消し込みが正常に機能しなかったり不具合が発生することがある。

一番シンプルで簡単なものはVBA操作の最初に3行を記入しておけば不具合は回避できる。

If ActiveSheet.FilterMode = True Then

         ActiveSheet.ShowAllData

End If

FilterModeはオートフィルタが絞り込まれているかどうか絞り込まれていればTrueを

絞り込まれていなければFalseが返されるので絞り込まれているときは

ShowAllDataで絞り込み解除するやり方である。

AutoFilterModeでオートフィルタが表示されているかどうかを判定したあとの処理でもよいがオートフィルタが表示されていない場合は上記の構文で判定はFalseが返されるのでオートフィルタの表示の有無にかかわらずこの3行で対処は可能である。

※オートフィルタを解除してVBA作業をしてあとでオートフィルタを表示を戻すやり方も考えられるが構文が複雑になり労多くして効果薄なので通常作業では避けたほうが無難である。

※すべてデータをクリアにしたい場合など絞り込みがされた状態では範囲を指定してクリアすると絞り込まれた箇所はクリアされないのでセルごとにクリアする手段もあるが非常に時間がかかり効率的でない。

VBA Modを使う(割り算の余りを求める)

10進法で作業が進めにくい場合もあります。意外と使い道があるので覚えてください。

まず、Excelでは 

答え「1」のところの数式は、

=MOD(A2,B2)   <R1C1参照形式:=MOD(RC[-2],RC[-1]) >

割られる数 割る数 余り
10 3 1


 VBAでは下のように記述します。

Sub Macro931()

Cells(2, 3) = Cells(2, 1) Mod Cells(2, 2)

End Sub

 

A1参照形式で記述すると下のようになります。

Range("C2") = Range("A2") Mod Range("B2")

Excelの数式とちょっと違うので気をつけてください。

セルに計算式を入れるなら

Sub Macro932()

Cells(2, 3) = "=MOD(RC[-2],RC[-1])"

End Sub

 

高校数学では<定義:合同式

2つの整数a,bを自然数nで割った余りが等しいとき
a≡b(mod n) と表しaとbはnを法として合同であるという。

 

a≡b (mod n) , c≡d (mod n)
a+c≡b+d (mod n)
a-c≡b-d (mod n)
ac≡bd (mod n)
a^p≡b^p (mod n)


問題1

f:id:ava7545:20200929083701p:plain を7で割った余りを求めよ。


問題2

f:id:ava7545:20200929082926p:plainの下2桁を求めよ。(2018昭和大学 医)

 

VBA R1C1参照形式からA1参照形式に変換

Excelは通常、A1参照形式で扱うことが多いがそれ以外にA列、B列ではなく列表示も数字のR1C1参照形式がある。

昭和世代にはロータス形式、マルチプラン形式のほうが馴染みやすいが今では通じない死語かも知れない。

VBAでは変数を扱う場合、数字のほうが変数処理をしやすいのでR1C1形式を使うことが多いがA1形式に変換したい場合がある。

例えば 53列をA1形式に変換に変換するには

Cells(1,1)= Cells(1,53).Address

$BA$1

知りたいのは「BA」なので$や1はいらない。

「BA」のみを抽出する方法は

 

Dim n As String
n = Cells(1, 53).Address(True, False)
Cells(1, 1) = Left(n, (InStr(n, "$") - 1))  ①
Cells(2, 1) = Left(n, (Len(n) - 2))     ②

BA
BA

または

Dim n As String
n = Cells(1, 53).Address(False, False)
Cells(1, 1) = Left(n, (Len(n) - 1))

BA

 

※ VBAの処理で行も可変の場合は①を使う必要がある。

 

Addressプロパティは

 expression.Address (RowAbsoluteColumnAbsoluteReferenceStyleExternalRelativeTo)

RowAbsolute・・行の部分True:絶対参照、False:相対参照

ColumnAbsolute・・列の部分True:絶対参照、False:相対参照

ReferenceStyle・・既定値は xlA1 

External・・既定値は False 

RelativeTo・・RowAbsolute、ColumnAbsolute両方Falseの場合でReferenceStyle が xlR1C1 である場合は、相対参照の開始点を含める必要がある

 

必要になる場面に遭遇することはあまりないがA1参照形式で処理した場合は使える。

 

 

 

 

 

VBA 空白(””)を含む数式を入れるときの処理

計算式が無効にならないように空白を考慮した計算式例

  1 2 3 4
1 出身県 人数 年俸 平均年俸(万円)
2 岐阜 1 1,800 =IF(RC[-2]<>"",RC[-1]/RC[-2],"")
3 静岡 4 32,770 =IF(RC[-2]<>"",RC[-1]/RC[-2],"")
4 愛知     =IF(RC[-2]<>"",RC[-1]/RC[-2],"")
5 三重 1 550 =IF(RC[-2]<>"",RC[-1]/RC[-2],"")
6 合計 =SUM(R =SUM(R  =IF(RC[-2]<>"",RC[-1]/RC[-2],"")

 

  1 2 3 4
1 出身県 人数 年俸合計(万円) 平均年俸(万円)
2 岐阜 1 1,800 1,800
3 静岡 4 32,770 8,193
4 愛知      
5 三重 1 550 550
6 合計 6 35,120 5,853

この空白を考慮した計算式をVBAでそのまま記述し実行すると

Cells(2, 4) = "=IF(RC[-2]<>"",RC[-1]/RC[-2],"")"

f:id:ava7545:20200926103954p:plain

エラーとなってしまいます。

VBA記述で文字列を括る(””)と空白(””)が判別できないからです。

 

計算式内での(””)とVBA記述での(””)を区別させるために計算式を以下のように分割します。

①=IF(RC[-2]<>

②””

③,RC[-1]/RC[-2],

④””

⑤)

さらに計算式内での(”)を認識させるために(”)を(””)にします。

ですから空白(””)は(””””)でやっと認識しくれるというわけです。

そして

”①” & "②" & "③" & "④" & "⑤"してしまえばいいわけです。

Cells(2, 4) = "=IF(RC[-2]<>" & """""" & ",RC[-1]/RC[-2]," & """""" & ")"

 

例えば

=IF(RC[-2]<>"",RC[-1]/RC[-2],"対象外") の場合

Cells(2, 4) = "=IF(RC[-2]<>" & """""" & ",RC[-1]/RC[-2]," & """対象外""" & ")"

 

 

VBA DateAdd関数

VBA DateAdd関数

指定した時間間隔を日付に加算してその日付を含む Variant (Date) を返します。

 

使用例

・販売予測と在庫数から在庫がなくなる日を予測します。

・在庫が無くなる予測日から補充発注をする日を割り出します。

 

 

DateAdd(interval, number, date)

DateAdd( 加減算する単位、加減算する数値、元になる日時 )

 

例:DateAdd("m", 1, Date)

 

interval引数の設定

 

設定  説明

"yyyy" 年

"q" 四半期

"m" 月

"y" 通年での日数

"d" 日

"w" 平日

"ww" 週

"h" 時

"n" 分

"s" 秒

 

"y"、"d"、"w"は同じ値が返ります。

 

VBA データベースの最終行を調べる

Excel VBAを使ってデータベースを集計するとき、レコードの最終行を知る必要がある。

私が最初に覚えたのがCurrentRegionプロパティで、例えば

GYO = Sheets("Data").Cells(1, 1).CurrentRegion.Rows.Count

Dataシートの1行目からデータが入っているものに有効な最終行調査である。

ところが、データベースを作る人によっては視覚的に見やすくするため空白行を挿入していたり、下記のように表題、凡例が説明されているようなものでは不都合がおきる。

  A B C
1 統計名: 基礎データ  
2 凡例 *** 未調査
3   - データなし
4   X 非公表
5      
6 地域 教育 幼稚園数
7 北海道   422
8 青森県   88
9 岩手県   97
10 宮城県   242
11 秋田県   40
12 山形県   74
13 福島県   264
14 茨城県   268
15 栃木県   100
16 群馬県   155
17 埼玉県   544
18 千葉県   510


gyo1 = Sheets("Data").Cells(1, 1).CurrentRegion.Rows.CountSub Macro4()

gyo2 = Sheets("Data").Cells(6, 1).CurrentRegion.Rows.Count

gyo3 = Sheets("Data").Cells(6, 2).CurrentRegion.Rows.Count


gyo4 = Sheets("Data").Range("A65536").End(xlUp).Row

gyo5 = Sheets("Data").Range("B65536").End(xlUp).Row


gyo6 = Sheets("Data").Cells(Rows.Count, 1).End(xlUp).Row

        gyo6 = Sheets("Data").Cells(Rows.Count, "A").End(xlUp).Row

gyo7 = Sheets("Data").Cells(Rows.Count, 2).End(xlUp).Row

       gyo7 = Sheets("Data").Cells(Rows.Count, "B").End(xlUp).Row

End Sub

 

  実行結果  
gyo1 4 表題案例部分をDBと判断
gyo2 13 データ部分の行数
6行~18行
gyo3 13
gyo4 18 A列の最終行(※)
gyo5 6 B列の最終行(※)
gyo6 18 A列の最終行
gyo7 6 B列の最終行

(※)Excel2003まではExcelの行数は65,536行であったがExcel2007以降では
1,048,576行まで拡張しているため65,536行を超えるようなデータの場合は使えない(65536行が
データ内のためデータの最上行を表示)。

 

データベースの構成、レコード(行)フィールド(列)などを見極めて使う必要がある。

 

<参考>6行目がデータのKey列の場合の最終列を調べる

retu1 = Sheets("Data").Cells(6, Columns.Count).End(xlToLeft).Column

 

VBA セルを色塗りする

 


データの内容に応じてセルの色を変えたい場合、VBAで処理をしなくてもExcelの「条件付き書式」で設定をしておけばいい。とは言えExcelデータで作業をしていると「条件付き書式」ではないほうがいいこともある。そんなときに活用したい。

例えば、VBAでデータ加工をして特に注意をはらってほしいデータがあるとする。そこに色塗りをしておき詳細なチェックを手作業で行い問題がなければ色塗りを消したい場合などに活用できる。

 

Sub Macro930()
Dim n As Integer
Dim m As Integer
Dim p As Integer

      For n = 0 To 56
           m = Int(n / 10) + 1
            p = n Mod 10 + 1
                   Cells(p, m).Interior.ColorIndex = n
      Next n
End Sub

f:id:ava7545:20200927071403p:plain

f:id:ava7545:20210101164926p:plain