忍者ブログ

列集計マクロの改良

2022年06月14日
3つ前の記事で、列集計マクロについて書いた。
今回はそのマクロの改良について。




きっかけとなった改良内容は次の2つ。
1.セルの文字から数字部分を除去すること。
2.左から指定した文字数だけ集計すること。

セルの内容を辞書型配列に格納するときに
上記の1,2を実装した関数を通せばいいだけ。

新しいプロシージャとしてコピペでソースをかけば動くわけだけど、
ソースが二重管理になるのでDRY原則(Don't Repeat Yourself)に反する。

そのまま改良を始めると、ソースがごちゃごちゃになりそうだったので、
リファクタリングを行った。

元々のモジュール名とその挙動は変更せず、
機能追加したモジュールを別途作成し、メインの処理を共通化した。

当初、動作オプション1つずつに別々の引数にしていたけど、
スマートじゃないので、文字列で受け渡すことにした。

調べた限り、VBAでは配列を引数として渡すことができないようなので、
数値型の4引数をカンマ区切りの文字列として渡して
受け側でSplit関数で配列に変換。要素数を指定して取り出すという処理にした。

2次元集計については、出力結果に対して
合計計算とカラースケールの追加、行列の並べ替えをしていたので、
その処理も合わせて追加した。リファクタリングツール様様でした。


面白いことに、作っているときはこれが最善手と思っているけど、
1日経てば全く違う解決策がぱっと浮かぶもんなんだな。

そしてその解決策もそもそも必要なかったという結論になったんだけど
それはまた別の話。

というわけで、以下ソース。 ソーステキストはこちら



Option Explicit '変数を先に宣言しなさいよ
Const debugFlag = 1


'Private Function getColNo(列1)
'Function get2dDicArr(colX As Long, colY As Long, tGyo As Long, edGyo As Long)
Sub ◆2列集計dic()

Dim strFlag As String: strFlag = 0 & "," & 0 & "," & 0 & "," & 0
Call ◆2列集計dic_main(strFlag)
End Sub


Sub ◆2列集計dic_rmNum()
'対象の2列を決定
Dim 列1 As Long: 列1 = Selection(1).Column
Dim 列2 As Long: 列2 = getCol2No()

Dim rmXflag: rmXflag = 7 - MsgBox(getStrCol(列1) & "列の数値を除外して集計しますか?", vbYesNo, "removeNumberCheck")
Dim numLenX: numLenX = InputBox(getStrCol(列1) & "列の集計対象の文字数を入力してください。" & Chr(10) & Chr(10) & "buf =left(removeNumber(buf),文字数)")
If numLenX = "" Then numLenX = 0
If IsNumeric(numLenX) = False Then errorEnd ("文字数は数値で入力してください。")

Dim rmYflag: rmYflag = 7 - MsgBox(getStrCol(列2) & "列の数値を除外して集計しますか?", vbYesNo, "removeNumberCheck")
Dim numLenY: numLenY = InputBox(Split(Cells(1, 列2).Address(True, False), "$")(0) & "列の集計対象の文字数を入力してください。" & Chr(10) & Chr(10) & "buf =left(removeNumber(buf),文字数)")
If numLenY = "" Then numLenY = 0
If IsNumeric(numLenY) = False Then errorEnd ("文字数は数値で入力してください。")

Dim strFlag As String: strFlag = rmXflag & "," & rmYflag & "," & numLenX & "," & numLenY
Call ◆2列集計dic_main(strFlag)
End Sub

Private Function getStrCol(ColNumber As Long) As String
'列番号を列文字に変換
getStrCol = Split(Cells(1, ColNumber).Address(True, False), "$")(0)
End Function

Sub ◆2列集計dic_main(strFlag As String)
'strFlag = rmXflag,rmYflag,numLenX,numLenY

Dim tictoc As Double
tictoc = Timer

Dim 列1 As Long: 列1 = Selection(1).Column
Dim 列2 As Long: 列2 = getCol2No()

'タイトル行を決定
Dim tGyo As Long: tGyo = 1
If Cells(1, 列1) = "" Then tGyo = Cells(1, 列1).End(xlDown).Row
If Cells(tGyo, 列2) = "" Then errorEnd ("タイトル行不一致")

'最終行を決定
Dim edGyo As Long: edGyo = Cells(Rows.Count, 列1).End(xlUp).Row
If Cells(edGyo, 列2) = "" Then errorEnd ("最終行不一致")

'選択中のセルから出力配列ゲット
Dim oArr: oArr = get2dDicArr(列1, 列2, tGyo, edGyo, strFlag) 'strFlag = rmXflag,rmYflag,numLenX,numLenY

'出力シート名
Dim shName As String: shName = oArr(0, 0): oArr(0, 0) = ""

'転置有無を判断して、セルフォーマットを取得
Dim xFormat As String, yFormat As String
If Cells(tGyo, 列1) & "‡" & Cells(tGyo, 列2) = shName Then '転置なし
xFormat = Cells(tGyo, 列1).Offset(1, 0).NumberFormatLocal
yFormat = Cells(tGyo, 列2).Offset(1, 0).NumberFormatLocal
ElseIf Cells(tGyo, 列2) & "‡" & Cells(tGyo, 列1) = shName Then '転置あり
yFormat = Cells(tGyo, 列1).Offset(1, 0).NumberFormatLocal
xFormat = Cells(tGyo, 列2).Offset(1, 0).NumberFormatLocal
Else
errorEnd ("なんか違う")
End If

Dim Xwth As Double: Xwth = Columns(列1).ColumnWidth
Dim Ywth As Double: Ywth = Columns(列2).ColumnWidth

Application.ScreenUpdating = False

'シート追加
Worksheets.Add

'同名がいなければリネーム
If IsWorksheetExists(shName) = False Then ActiveSheet.Name = shName

'出力先を指定し、列幅、書式を設定
Dim OutPutCell As range: Set OutPutCell = Cells(2, 2) '出力する範囲の左上
Dim oRange As range: Set oRange = OutPutCell.Resize(UBound(oArr, 1), UBound(oArr, 2))
Dim afRange As range: Set afRange = OutPutCell.Resize(UBound(oArr, 1), UBound(oArr, 2) + 1)

oRange.ColumnWidth = Ywth
OutPutCell.ColumnWidth = Xwth

OutPutCell.Resize(UBound(oArr, 1), UBound(oArr, 2)).NumberFormatLocal = "#,##0"
OutPutCell.Resize(UBound(oArr, 1), 1).NumberFormatLocal = xFormat
OutPutCell.Resize(1, UBound(oArr, 2)).NumberFormatLocal = yFormat

'配列をセルに格納
Call ArrayToCell(OutPutCell, oArr)

OutPutCell.Offset(1, 1).Select
ActiveWindow.FreezePanes = True
afRange.AutoFilter
afRange.CurrentRegion.Borders.LineStyle = xlContinuous

'シート名から項目タイトルを入力
Dim tBuf: tBuf = Split(shName, "‡")
OutPutCell.Offset(-1, 0) = "「" & tBuf(0) & "」×「" & tBuf(1) & "」のピボット(" & ActiveWorkbook.Name & ")"

'印刷レイアウト変更 余白狭いで1枚幅印刷レイアウト
Dim yohakuFlag As Boolean: yohakuFlag = True
Call PrintPageSetup(yohakuFlag)


'レンジを指定して条件付き書式のカラースケールを設定
Dim csRange As range: Set csRange = OutPutCell.Offset(1, 1).Resize(UBound(oArr, 1) - 1, UBound(oArr, 2) - 1)
Call setColorScale(csRange)

'合計の追記
Dim stRow As Long: stRow = csRange(1).Row
Dim stCol As Long: stCol = csRange(1).Column
Dim edRow As Long: edRow = csRange(csRange.Count).Row
Dim edCol As Long: edCol = csRange(csRange.Count).Column
Cells(stRow - 1, edCol + 1) = "合計"

Dim c As Long, r As Long
For r = stRow To edRow
Cells(r, edCol + 1) = WorksheetFunction.Sum(range(Cells(r, stCol), Cells(r, edCol)))
Next r
For c = stCol To edCol + 1
Cells(stRow - 2, c) = WorksheetFunction.Sum(range(Cells(stRow, c), Cells(edRow, c)))
Next c

'列の並べ替え
With ActiveSheet.Sort
.SortFields.Add key:=range(Cells(stRow - 2, stCol), Cells(stRow - 2, edCol)), _
SortOn:=xlSortOnValues, _
Order:=xlDescending, _
DataOption:=xlSortNormal
.SetRange range(oRange(1).Offset(-1, 1), oRange(oRange.Count))
.Header = xlNo 'xlGuess
.MatchCase = False
.Orientation = xlLeftToRight
.SortMethod = xlPinYin
.Apply
End With

'行の並べ替え
With ActiveSheet.AutoFilter.Sort
.SortFields.Add key:=range(Cells(stRow, edCol + 1), Cells(edRow, edCol + 1)), _
SortOn:=xlSortOnValues, _
Order:=xlDescending, _
DataOption:=xlSortNormal
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Application.ScreenUpdating = True

If debugFlag Then Debug.Print "ex[" & Now & "] "; Format(Timer - tictoc, "0.00秒")
If debugFlag Then Call シート比較自動試験
End Sub

Sub setColorScale(tarRange As range)
tarRange.FormatConditions.AddColorScale ColorScaleType:=2
tarRange.FormatConditions(tarRange.FormatConditions.Count).SetFirstPriority
tarRange.FormatConditions(1).ColorScaleCriteria(1).Type = xlConditionValueLowestValue
With tarRange.FormatConditions(1).ColorScaleCriteria(1).FormatColor
.Color = 16776444
.TintAndShade = 0
End With
tarRange.FormatConditions(1).ColorScaleCriteria(2).Type = xlConditionValueHighestValue
With tarRange.FormatConditions(1).ColorScaleCriteria(2).FormatColor
.Color = 7039480
.TintAndShade = 0
End With
End Sub
Private Function getCol2No()
Dim 列1 As Long: 列1 = Selection(1).Column
Dim 列s As Long: 列s = Selection(Selection.Count).Column '複数セレクション
Dim 列a As Long: 列a = Selection.Areas(Selection.Areas.Count).Column 'エリア
Dim 列2 As Long '選択範囲から2つの列を決定して集計
If 列1 <> 列a Then
列2 = 列a
ElseIf 列1 <> 列s Then
列2 = 列s
Else
errorEnd ("複数列を選択して実行してください。")
End If
getCol2No = 列2
End Function

Function getTimeFlag(sampleRange As range)
Dim timeFlag: timeFlag = 0
If IsNumeric(sampleRange) And InStr(sampleRange.text, ":") > 0 Then '文字列で:を含み、数値型で小数部が0以上
timeFlag = (sampleRange.Value > 0) * (sampleRange.Value - Int(sampleRange.Value) >= 0)
End If
getTimeFlag = timeFlag
End Function

'出力配列を取得 Arr(0,0)はタイトル
Function get2dDicArr(colX As Long, colY As Long, tGyo As Long, edGyo As Long, strFlag As String)
'strFlag = rmXflag,rmYflag,numLenX,numLenY
Dim flagArr: flagArr = Split(strFlag, ",")
Dim numLenX As Long: numLenX = flagArr(2)
Dim numLenY As Long: numLenY = flagArr(3)

'データと書式の確認 X と Y それぞれ
Dim myArrX: myArrX = range(Cells(tGyo, colX), Cells(edGyo, colX)).Value
Dim myArrY: myArrY = range(Cells(tGyo, colY), Cells(edGyo, colY)).Value

'時刻型かを関数で判定
Dim timeFlagX: timeFlagX = getTimeFlag(Cells(tGyo, colX).Offset(1, 0))
Dim timeFlagY: timeFlagY = getTimeFlag(Cells(tGyo, colY).Offset(1, 0))

'出力先のフォーマットを取得
Dim formatX: formatX = Cells(tGyo, colX).Offset(1, 0).NumberFormatLocal
Dim formatY: formatY = Cells(tGyo, colY).Offset(1, 0).NumberFormatLocal

'時刻型は文字列変換処理
Dim i As Long
If timeFlagX > 0 Then
For i = 2 To UBound(myArrX)
myArrX(i, 1) = Format(myArrX(i, 1), formatX)
Next i
End If
If timeFlagY > 0 Then
For i = 2 To UBound(myArrY)
myArrY(i, 1) = Format(myArrY(i, 1), formatY)
Next i
End If

'rmXflag > 0 の場合
If flagArr(0) > 0 Then 'flagArr =[rmXflag,rmYflag,numLenX,numLenY]
For i = 2 To UBound(myArrX)
myArrX(i, 1) = removeNumber(myArrX(i, 1))
Next i
End If
'rmYflag > 0 の場合
If flagArr(1) > 0 Then 'flagArr =[rmXflag,rmYflag,numLenX,numLenY]
For i = 2 To UBound(myArrY)
myArrY(i, 1) = removeNumber(myArrY(i, 1))
Next i
End If

'文字列の絞り込み処理
If numLenX = 0 Then '通常集計の場合
'なにもしない
ElseIf numLenX > 0 Then
For i = 2 To UBound(myArrX)
myArrX(i, 1) = Left(myArrX(i, 1), numLenX)
Next i
ElseIf numLenX < 0 Then
For i = 2 To UBound(myArrX)
myArrX(i, 1) = Right(myArrX(i, 1), Abs(numLenX))
Next i
End If
If numLenY = 0 Then '通常集計の場合
'なにもしない
ElseIf numLenY > 0 Then
For i = 1 To UBound(myArrY)
myArrY(i, 1) = removeNumber(Left(myArrY(i, 1), numLenY))
Next i
ElseIf numLenY < 0 Then
For i = 1 To UBound(myArrY)
myArrY(i, 1) = removeNumber(Right(myArrY(i, 1), Abs(numLenY)))
Next i
End If

'ポインタDic
Dim DicX, DicY, DicZ
Set DicX = CreateObject("Scripting.Dictionary")
Set DicY = CreateObject("Scripting.Dictionary")
Set DicZ = CreateObject("Scripting.Dictionary")

Dim cntX As Long, cntY As Long, cntZ As Long
Dim bufX As String, bufY As String, bufZ As String
For i = 1 To UBound(myArrX)
bufX = myArrX(i, 1)
If Not DicX.exists(bufX) Then
DicX.Add bufX, cntX
cntX = cntX + 1
End If

bufY = myArrY(i, 1)
If Not DicY.exists(bufY) Then
DicY.Add bufY, cntY
cntY = cntY + 1
End If

bufZ = bufX & "‡" & bufY
If Not DicZ.exists(bufZ) Then
DicZ.Add bufZ, 1
Else
DicZ(bufZ) = DicZ(bufZ) + 1
End If
Next i
Set myArrX = Nothing: Set myArrY = Nothing

Dim KeysX: KeysX = DicX.keys
Dim KeysY: KeysY = DicY.keys
Dim KeysZ: KeysZ = DicZ.keys

'要素数から転置判定
Const MaxColumns = 1024 '列上限は16384
Dim trnsFlag As Boolean, msg As String
If DicX.Count > MaxColumns And DicY.Count > MaxColumns Then
errorEnd ("2列ともに要素数が大きすぎます")
ElseIf DicX.Count > MaxColumns Then
trnsFlag = False
ElseIf DicY.Count > MaxColumns Then
trnsFlag = True
ElseIf DicY.Count > DicX.Count Then
msg = "列データ数 > 行データ数 ですが転置しますか?" & Chr(10) _
& KeysY(0) & " : " & DicY.Count & " > " & KeysX(0) & " : " & DicX.Count
If MsgBox(msg, vbYesNo) = vbYes Then
trnsFlag = True
Else
trnsFlag = False
End If
Else
trnsFlag = False
End If

'転置の有無に配慮して、出力配列を作成
Dim buf, oArr()
Dim j As Long, k As Long
If trnsFlag = False Then
ReDim oArr(DicX.Count, DicY.Count)
For i = 1 To UBound(KeysX)
For j = 1 To UBound(KeysY)
oArr(i, j) = 0
Next j
Next i
For i = 1 To UBound(KeysX)
oArr(i, 0) = KeysX(i)
Next i
For j = 1 To UBound(KeysY)
oArr(0, j) = KeysY(j)
Next j
For k = 1 To UBound(KeysZ)
buf = Split(KeysZ(k), "‡")
oArr(DicX(buf(0)), DicY(buf(1))) = DicZ(KeysZ(k))
Next k
oArr(0, 0) = KeysX(0) & "‡" & KeysY(0)
Else
ReDim oArr(DicY.Count, DicX.Count)
For i = 1 To UBound(KeysX)
For j = 1 To UBound(KeysY)
oArr(j, i) = 0
Next j
Next i
For i = 1 To UBound(KeysX)
oArr(0, i) = KeysX(i)
Next i
For j = 1 To UBound(KeysY)
oArr(j, 0) = KeysY(j)
Next j
For k = 1 To UBound(KeysZ)
buf = Split(KeysZ(k), "‡")
oArr(DicY(buf(1)), DicX(buf(0))) = DicZ(KeysZ(k))
Next k
oArr(0, 0) = KeysY(0) & "‡" & KeysX(0)
End If
get2dDicArr = oArr
End Function

Sub ◆1列集計dic_rmNum()

Dim rmXflag: rmXflag = 7 - MsgBox(getStrCol(Selection.Column) & "列の数値を除外して集計しますか?", vbYesNo, "removeNumberCheck")
Dim numLen: numLen = InputBox(Split(Selection.Address(True, False), "$")(0) & "列の集計対象の文字数を入力してください。" & Chr(10) & Chr(10) & "buf =left(removeNumber(buf),文字数)")
If numLen = "" Then numLen = 0

If IsNumeric(numLen) = False Then errorEnd ("文字数は数値で入力してください。")

Dim strFlag As String: strFlag = rmXflag & "," & numLen
Call ◆1列集計dic_main(strFlag)
End Sub

Sub ◆1列集計dic()
Dim strFlag As String: strFlag = 0 & "," & 0
Call ◆1列集計dic_main(strFlag)
End Sub

Sub ◆1列集計dic_main(strFlag As String)

Dim tictoc As Double: tictoc = Timer

Dim col As Long: col = Selection.Column

Dim tGyo As Long: tGyo = 1
If Cells(1, col) = "" Then tGyo = Cells(1, col).End(xlDown).Row 'タイトル行

Dim edGyo As Long: edGyo = Cells(Rows.Count, col).End(xlUp).Row '最終行
If edGyo <= tGyo Then Call errorEnd("データがありません")

'出力配列ゲット
Dim oArr: oArr = get1dDicArr(col, tGyo, edGyo, strFlag)

'データと書式の確認
Dim cWidth As Long: cWidth = Selection.ColumnWidth
Dim formatX: formatX = Cells(tGyo, col).Offset(1, 0).NumberFormatLocal

Application.ScreenUpdating = False

'シート追加
Worksheets.Add
'シート名が重複しなければリネーム
Dim shName As String: shName = oArr(0, 1) & "_内訳"
If IsWorksheetExists(shName) = False Then ActiveSheet.Name = shName

Columns(1).ColumnWidth = 5
Columns(2).ColumnWidth = cWidth

Const タイトル行 = 2
Dim 格納最終行 As Long: 格納最終行 = UBound(oArr, 1) + 1
range("B" & タイトル行 + 1 & ":B" & 格納最終行).NumberFormatLocal = formatX
range("C" & タイトル行 + 1 & ":C" & 格納最終行).NumberFormatLocal = "#,##0"
range("D" & タイトル行 + 1 & ":D" & 格納最終行).NumberFormatLocal = "0.00%"
range("E" & タイトル行 + 1 & ":E" & 格納最終行).Font.Name = "HGP明朝E"

'セルを指定して、oArrを出力
Dim OutPutCell As range: Set OutPutCell = Cells(タイトル行, 1)
Call ArrayToCell(OutPutCell, oArr)

'ウィンドウ枠の固定
OutPutCell.Offset(1, 1).Select
ActiveWindow.FreezePanes = True

'オートフィルタしてソート
OutPutCell.AutoFilter
With ActiveSheet.AutoFilter.range
.Sort Key1:=.range("C2"), Order1:=xlDescending, Header:=xlYes
.CurrentRegion.Borders.LineStyle = xlContinuous
End With

'配列からセルへ貼り付け
Call ArrayToCell(OutPutCell, oArr, 1)

'欄外に情報を記載
Cells(1, 1) = Format(UBound(oArr) - 1, "#,##0種")
Cells(1, 2).HorizontalAlignment = xlRight
Cells(1, 2) = "合計:"
Cells(1, 3) = Format(edGyo - tGyo, "#,##0件")

'印刷レイアウト変更 1枚幅印刷レイアウト
Dim yohakuFlag As Boolean: yohakuFlag = False
Call PrintPageSetup(yohakuFlag)

Application.ScreenUpdating = True
If debugFlag = 1 Then Debug.Print "[" & Now & "] "; "EX" & Format(edGyo - 1, "#,##0行を") & Format(Timer - tictoc, "0.00秒")
If debugFlag Then Call シート比較自動試験
End Sub


'出力配列を取得
Function get1dDicArr(col As Long, tGyo As Long, edGyo As Long, strFlag As String)
Const gLimit = 1000 'ゲージ表示上限
Dim flagArr: flagArr = Split(strFlag, ",") ' rmFlag,numLen

'データと書式の確認
Dim timeFlag: timeFlag = getTimeFlag(Cells(tGyo, col).Offset(1, 0))
Dim formatX: formatX = Cells(tGyo, col).Offset(1, 0).NumberFormatLocal

Dim ColName As String: ColName = Cells(tGyo, col).text '列タイトル
Dim MyArr: MyArr = range(Cells(tGyo + 1, col), Cells(edGyo, col)).Value

Dim i As Long
If timeFlag > 0 Then '時刻型は別扱い
For i = 1 To UBound(MyArr)
MyArr(i, 1) = Format(MyArr(i, 1), formatX)
Next i
End If

If flagArr(0) > 0 Then 'rmNumあり
For i = 1 To UBound(MyArr)
MyArr(i, 1) = removeNumber(MyArr(i, 1))
Next i
End If

If flagArr(1) = 0 Then '通常集計の場合
'なにもしない
ElseIf flagArr(1) > 0 Then
For i = 1 To UBound(MyArr)
MyArr(i, 1) = Left(MyArr(i, 1), flagArr(1))
Next i
ElseIf flagArr(1) < 0 Then
For i = 1 To UBound(MyArr)
MyArr(i, 1) = Right(MyArr(i, 1), Abs(flagArr(1)))
Next i
End If

Dim buf As String
Dim dic: Set dic = CreateObject("Scripting.Dictionary")
For i = 1 To UBound(MyArr)
buf = MyArr(i, 1)
If Not dic.exists(buf) Then
dic.Add buf, 1
Else
dic(buf) = dic(buf) + 1
End If
Next i

''出力
Dim oArr() As Variant: ReDim oArr(dic.Count + 1, 4)

oArr(0, 0) = "№"
oArr(0, 1) = ColName
oArr(0, 2) = "件"
oArr(0, 3) = "割合"
oArr(0, 4) = "ゲージ"
Const ゲージ文字 = "|"

Dim keys: keys = dic.keys
If dic.Count < gLimit Then
For i = 0 To dic.Count - 1
oArr(i + 1, 0) = i + 1
oArr(i + 1, 1) = keys(i)
oArr(i + 1, 2) = dic(keys(i))
oArr(i + 1, 3) = dic(keys(i)) / (edGyo - tGyo)
oArr(i + 1, 4) = Application.WorksheetFunction.Rept(ゲージ文字, dic(keys(i)) * dic.Count / (edGyo - tGyo) * 1 \ 1)
Next i
Else '件数が多い場合はゲージを出さない
For i = 0 To dic.Count - 1
oArr(i + 1, 0) = i + 1
oArr(i + 1, 1) = keys(i)
oArr(i + 1, 2) = dic(keys(i))
Next i
End If
Set dic = Nothing
get1dDicArr = oArr
End Function


Function removeNumber(inputStr)
Dim i As Long
For i = 0 To 9
inputStr = Replace(inputStr, i, "")
Next i
removeNumber = inputStr
End Function

Private Sub PrintPageSetup(Optional yohakuFlag As Boolean = False)

'印刷レイアウト変更 余白狭いで1枚幅印刷レイアウト
With ActiveSheet.PageSetup
Application.PrintCommunication = False
.PrintTitleRows = "$2:$2"
.CenterHorizontally = True '中央寄せに
If yohakuFlag Then '余白変更ありの場合
.LeftMargin = Application.InchesToPoints(0.25)
.RightMargin = Application.InchesToPoints(0.25)
.TopMargin = Application.InchesToPoints(0.75)
.BottomMargin = Application.InchesToPoints(0.75)
.HeaderMargin = Application.InchesToPoints(0.3)
.FooterMargin = Application.InchesToPoints(0.3)
End If
.FitToPagesWide = 1 '横何ページ分で収めるか
.FitToPagesTall = 0 '自動は0。指定しないと1になる。
.RightHeader = "&D"
.CenterFooter = "&P/&N"
Application.PrintCommunication = True
End With
End Sub

'2次元配列をシートに貼り付ける便利モジュール
Sub ArrayToCell(Target As range, oArr, Optional ColCnt As Long = 0)
Dim iRowMax: iRowMax = UBound(oArr, 1) - LBound(oArr, 1) + 1 '// 1次元目の要素数を取得 '// 二次元配列の最大行数
Dim iColMax: iColMax = UBound(oArr, 2) - LBound(oArr, 2) + 1 '// 2次元目の要素数を取得'// 二次元配列の最大列数

'// Rangeオブジェクトで開始セルから貼り付けるセル範囲を拡張する場合
If ColCnt > 0 And ColCnt <= iColMax Then
Target.Resize(iRowMax, ColCnt).Value = oArr
Else
Target.Resize(iRowMax, iColMax).Value = oArr
End If
End Sub

Private Function IsWorksheetExists(シート名 As String) As Boolean 'シートループで同じシート名があるかチェック あればTrue
Dim WS As Worksheet, flag As Boolean
For Each WS In Worksheets
If WS.Name = シート名 Then flag = True '開いたファイルに目的の名前のシートがあるか?
Next WS
IsWorksheetExists = flag
End Function

'エラー発生時にメッセージを出力して終了させる
Private Sub errorEnd(msg)
Application.ScreenUpdating = True 'おまじない
MsgBox msg
End
End Sub



PR
Comment
  Vodafone絵文字 i-mode絵文字 Ezweb絵文字