fork download
  1. Option Explicit
  2. Const Pmax As Long = 100 '従業員人の最大数
  3. Const Rmax As Long = 600 '1ピボットシート内の1人のひと月の最大行数
  4.  
  5. Dim HON1Rows(Pmax, Rmax) As Long '本年1部の行情報
  6. ' 左側の添字=各個人に割当られた番号(0-100)
  7. ' 右側の添字=0番目は以降の要素数を示す。(例 この値が3の時、要素数3なので、3番目の添字まで有効)
  8. ' 右側の添字=1番目以降は、行番号を示す。
  9. Dim HON2Rows(Pmax, Rmax) As Long '本年2部の行情報(添字は本年1部と同様)
  10. Dim HON3Rows(Pmax, Rmax) As Long '本年3部の行情報(添字は本年1部と同様)
  11. Dim HON1dicT As Object '本年1部の辞書 キー:支店名+課名+個人名 値:行情報テーブルの添字(0-100)
  12. Dim HON2dicT As Object '本年2部の辞書 (キーと値は本年1部と同様)
  13. Dim HON3dicT As Object '本年3部の辞書 (キーと値は本年1部と同様)
  14. Const HON1sheet As String = "1部本年P"
  15. Const HON2sheet As String = "2部本年P"
  16. Const HON3sheet As String = "3部本年P"
  17. Const JISSEKI As String = "実績" '実績
  18. Const ZENNEN As String = "前年" '前年
  19. Dim Uri_book As String '売上明細データブック名
  20. Dim trg_yyyy As Long '指定年
  21. Dim trg_mm As Long '指定月
  22. Dim Jis_folder As String '実績フォルダ
  23. Dim Kei_folder As String '計画フォルダ
  24. Dim trg_key As String '個人名キー
  25. Dim trg_col As Long '算出カラム番号
  26. Dim trg_mode As String '実績/前年
  27. Dim warnP As String '警告従業員
  28. Public Sub 売上月単位集計()
  29. Dim ws As Worksheet
  30. Dim yyyy, mm, ext As Variant
  31. Dim t1, t2 As Variant
  32. Dim Uri_path As String
  33. Set HON1dicT = CreateObject("Scripting.Dictionary")
  34. Set HON2dicT = CreateObject("Scripting.Dictionary")
  35. Set HON3dicT = CreateObject("Scripting.Dictionary")
  36. Set ws = Worksheets("管理")
  37. yyyy = ws.Cells(2, "A").Value '集計年
  38. If yyyy = "" Or IsNumeric(yyyy) = False Then
  39. MsgBox ("集計年月が不正")
  40. Exit Sub
  41. End If
  42. trg_yyyy = yyyy
  43. If trg_yyyy < 2010 Or trg_yyyy > 2099 Then
  44. MsgBox ("集計年月(2010-2099)が範囲外")
  45. Exit Sub
  46. End If
  47. mm = ws.Cells(2, "B").Value '集計月
  48. If mm = "" Or IsNumeric(mm) = False Then
  49. MsgBox ("集計月が不正")
  50. Exit Sub
  51. End If
  52. trg_mm = mm
  53. If trg_mm < 1 Or trg_mm > 12 Then
  54. MsgBox ("集計月(1-12)が範囲外")
  55. Exit Sub
  56. End If
  57. trg_mode = ws.Cells(2, "C").Value '集計項目
  58. If trg_mode <> JISSEKI And trg_mode <> ZENNEN Then
  59. MsgBox ("集計項目が不正")
  60. Exit Sub
  61. End If
  62. Jis_folder = ws.Cells(2, "D").Value '実績フォルダ名
  63. Uri_book = ws.Cells(2, "E").Value '実績売上明細ファイル
  64. '拡張子のチェック
  65. ext = Right(LCase(Uri_book), 5)
  66. If ext <> ".xlsx" And ext <> ".xlsm" Then
  67. MsgBox ("実績ファイル名が不正")
  68. Exit Sub
  69. End If
  70. Kei_folder = ws.Cells(2, "F").Value '計画フォルダ名
  71.  
  72. If Dir(Jis_folder, vbDirectory) = "" Then
  73. MsgBox ("実績フォルダが存在しません<" & Jis_folder & ">")
  74. Exit Sub
  75. End If
  76. If Dir(Kei_folder, vbDirectory) = "" Then
  77. MsgBox ("計画フォルダが存在しません<" & Kei_folder & ">")
  78. Exit Sub
  79. End If
  80. '売上明細ブック名設定
  81. Uri_path = Jis_folder & "\" & Uri_book
  82. 'MsgBox ("ファイル名<" & Uri_book & ">") '追加①
  83. 'MsgBox ("フルパス名<" & Uri_path & ">") '追加②
  84. 'MsgBox (GetAttr(Uri_path)) '追加③
  85. If Dir(Uri_path) = "" Then
  86. MsgBox (Uri_path & "が存在しません")
  87. Exit Sub
  88. End If
  89.  
  90. If MsgBox(trg_yyyy & "年" & trg_mm & "月の" & trg_mode & "を" & Uri_book & "から集計します", vbOKCancel) <> vbOK Then Exit Sub
  91. t1 = Timer
  92. warnP = ""
  93. Application.ScreenUpdating = False
  94. '売上明細ブック名オープン
  95. Workbooks.Open Uri_path
  96. Workbooks(Uri_book).Activate
  97. 'ピボットデータ読み込み
  98. Call readPivot(HON1sheet, HON1dicT, HON1Rows)
  99. Call readPivot(HON2sheet, HON2dicT, HON2Rows)
  100. Call readPivot(HON3sheet, HON3dicT, HON3Rows)
  101. Call OutPivot 'ピボット情報出力・・・・・追加①
  102. '計画フォルダ内の全ブックを更新する
  103. Call UpdateAllBooks(Kei_folder)
  104. Workbooks(Uri_book).Close
  105. Application.ScreenUpdating = True
  106. t2 = Timer
  107. MsgBox ("処理完了 所要時間(秒)=" & t2 - t1)
  108. If warnP <> "" Then
  109. MsgBox ("下記従業員は、1部,2部,3部の何れのピボットにも集計月のデータなし。" & vbLf & warnP)
  110. End If
  111. End Sub
  112.  
  113. '計画フォルダ内の全てのブックを更新する
  114. Private Sub UpdateAllBooks(ByVal Kei_folder As String)
  115. Dim bookname As String
  116. bookname = Dir(Kei_folder & "\*.xlsx", vbNormal)
  117. If bookname = "" Then
  118. MsgBox (Kei_folder & "内に支店別&課別(個人データ)ブックが存在しません。")
  119. End
  120. End If
  121. '全てのブックを更新する
  122. Do While bookname <> ""
  123. Call Update1Book(Kei_folder, bookname)
  124. bookname = Dir()
  125. Loop
  126. End Sub
  127.  
  128. '1つのブックを更新する
  129. Private Sub Update1Book(ByVal Kei_folder As String, ByVal bookname As String)
  130. Dim ws As Worksheet
  131. Dim i As Long
  132. Workbooks.Open Kei_folder & "\" & bookname
  133. '左側のシートから順に処理する
  134. For i = 1 To Worksheets.count
  135. Set ws = Worksheets(i)
  136. '合計シート検出時、終了
  137. If ws.name = "合計" Then Exit For
  138. If ws.name = "拠点計" Then Exit For '追加②
  139. '1つのシートを更新する
  140. Call Update1Sheet(bookname, ws)
  141. Next
  142. 'ブックを保存し、閉じる
  143. Workbooks(bookname).Save
  144. Workbooks(bookname).Close
  145. End Sub
  146. '1つのシートを更新する
  147. Private Sub Update1Sheet(ByVal bookname As String, ByVal ws As Worksheet)
  148. '支店名+課名+担当者名
  149. trg_key = ws.Cells(2, "C").Value & "|" & ws.Cells(3, "C").Value & "|" & ws.Cells(4, "C").Value
  150. '1部,2部,3部のピボットシート内に担当者の集計月の行が1件もない場合は、警告メッセージを出力し、その担当者をスキップする
  151. If HON1dicT.exists(trg_key) = False And HON2dicT.exists(trg_key) = False And HON3dicT.exists(trg_key) = False Then
  152. warnP = warnP & bookname & "(" & ws.name & ")" & trg_key & vbLf
  153. End If
  154. '集計月に対応するカラム位置を取得
  155. trg_col = GetColNumber(trg_mm)
  156. '個人シートに値を設定する
  157. Call set_value(bookname, ws, trg_mode)
  158. End Sub
  159. '個人シートに値の設定を行う
  160. Private Sub set_value(ByVal bookname As String, ByVal ws As Worksheet, ByVal mode As String)
  161. Dim col1 As Long '数量のカラム位置
  162. Dim col2 As Long '粗利のカラム位置
  163. 'カラム位置の設定
  164. col1 = trg_col + 3
  165. col2 = trg_col + 8
  166. '実績(当年)の場合は1カラム右へ設定
  167. If mode = JISSEKI Then
  168. col1 = col1 + 1
  169. col2 = col2 + 1
  170. End If
  171. '3部集計
  172. ' PVシート名,取得列,条件列,条件値,PV辞書,PV行情報
  173. ws.Cells(9, col1).Value = GetValue(HON3sheet, "I", "H", "1", HON3dicT, HON3Rows) 'A(数量)
  174. ws.Cells(9, col2).Value = GetValue(HON3sheet, "K", "H", "1", HON3dicT, HON3Rows) 'A(粗利)
  175. ws.Cells(10, col1).Value = GetValue(HON3sheet, "I", "H", "2", HON3dicT, HON3Rows) 'B(数量)
  176. ws.Cells(10, col2).Value = GetValue(HON3sheet, "K", "H", "2", HON3dicT, HON3Rows) 'B(粗利)
  177. ws.Cells(11, col1).Value = GetValue(HON3sheet, "I", "H", "3", HON3dicT, HON3Rows) 'C(数量)
  178. ws.Cells(11, col2).Value = GetValue(HON3sheet, "K", "H", "3", HON3dicT, HON3Rows) 'C(粗利)
  179. ws.Cells(12, col1).Value = GetValue(HON3sheet, "I", "H", "4", HON3dicT, HON3Rows) 'D(数量)
  180. ws.Cells(12, col2).Value = GetValue(HON3sheet, "K", "H", "4", HON3dicT, HON3Rows) 'D(粗利)
  181. ws.Cells(13, col1).Value = GetValue(HON3sheet, "I", "H", "5", HON3dicT, HON3Rows) 'E(数量)
  182. ws.Cells(13, col2).Value = GetValue(HON3sheet, "K", "H", "5", HON3dicT, HON3Rows) 'E(粗利)
  183. ws.Cells(14, col1).Value = GetValue(HON3sheet, "I", "H", "6", HON3dicT, HON3Rows) 'F(数量)
  184. ws.Cells(14, col2).Value = GetValue(HON3sheet, "K", "H", "6", HON3dicT, HON3Rows) 'F(粗利)
  185. ws.Cells(15, col1).Value = GetValue(HON3sheet, "I", "H", "7", HON3dicT, HON3Rows) 'G(数量)
  186. ws.Cells(15, col2).Value = GetValue(HON3sheet, "K", "H", "7", HON3dicT, HON3Rows) 'G(粗利)
  187. ws.Cells(16, col1).Value = GetValue(HON3sheet, "I", "H", "8", HON3dicT, HON3Rows) 'H(数量)
  188. ws.Cells(16, col2).Value = GetValue(HON3sheet, "K", "H", "8", HON3dicT, HON3Rows) 'H(粗利)
  189. ws.Cells(17, col1).Value = GetValue(HON3sheet, "I", "H", "9", HON3dicT, HON3Rows) 'I(数量)
  190. ws.Cells(17, col2).Value = GetValue(HON3sheet, "K", "H", "9", HON3dicT, HON3Rows) 'I(粗利)
  191. ws.Cells(18, col1).Value = GetValue(HON3sheet, "J", "F", "10", HON3dicT, HON3Rows) 'J(数量)
  192. ws.Cells(18, col2).Value = GetValue(HON3sheet, "K", "F", "10", HON3dicT, HON3Rows) 'J(粗利)
  193. '1部集計
  194. ws.Cells(20, col1).Value = GetValue(HON1sheet, "I", "H", "1", HON1dicT, HON1Rows) 'K(数量)
  195. ws.Cells(20, col2).Value = GetValue(HON1sheet, "K", "H", "1", HON1dicT, HON1Rows) 'K(粗利)
  196. ws.Cells(21, col1).Value = GetValue(HON1sheet, "I", "H", "2", HON1dicT, HON1Rows) 'L(数量)
  197. ws.Cells(21, col2).Value = GetValue(HON1sheet, "K", "H", "2", HON1dicT, HON1Rows) 'L(粗利)
  198. ws.Cells(22, col1).Value = GetValue(HON1sheet, "I", "H", "3", HON1dicT, HON1Rows) 'M(数量)
  199. ws.Cells(22, col2).Value = GetValue(HON1sheet, "K", "H", "3", HON1dicT, HON1Rows) 'M(粗利)
  200. ws.Cells(23, col1).Value = GetValue(HON1sheet, "I", "H", "4", HON1dicT, HON1Rows) 'N(数量)
  201. ws.Cells(23, col2).Value = GetValue(HON1sheet, "K", "H", "4", HON1dicT, HON1Rows) 'N(粗利)
  202. ws.Cells(24, col1).Value = GetValue(HON1sheet, "I", "H", "5", HON1dicT, HON1Rows) 'O(数量)
  203. ws.Cells(24, col2).Value = GetValue(HON1sheet, "K", "H", "5", HON1dicT, HON1Rows) 'O(粗利)
  204. ws.Cells(26, col1).Value = GetValue(HON1sheet, "J", "F", "1", HON1dicT, HON1Rows) 'P(数量)
  205. ws.Cells(26, col2).Value = GetValue(HON1sheet, "K", "F", "1", HON1dicT, HON1Rows) 'P(粗利)
  206. ws.Cells(27, col1).Value = GetValue(HON1sheet, "J", "F", "2", HON1dicT, HON1Rows) 'Q(数量)
  207. ws.Cells(27, col2).Value = GetValue(HON1sheet, "K", "F", "2", HON1dicT, HON1Rows) 'Q(粗利)
  208. '2部集計
  209. ws.Cells(30, col1).Value = GetValue(HON2sheet, "F", "B", "4", HON2dicT, HON2Rows) '1(数量)
  210. ws.Cells(30, col2).Value = GetValue(HON2sheet, "H", "B", "4", HON2dicT, HON2Rows) '1(粗利)
  211. ws.Cells(31, col1).Value = GetValue(HON2sheet, "F", "B", "5", HON2dicT, HON2Rows) '2(数量)
  212. ws.Cells(31, col2).Value = GetValue(HON2sheet, "H", "B", "5", HON2dicT, HON2Rows) '2(粗利)
  213. ws.Cells(32, col1).Value = GetValue(HON2sheet, "G", "B", "6", HON2dicT, HON2Rows) '3(数量)
  214. ws.Cells(32, col2).Value = GetValue(HON2sheet, "H", "B", "6", HON2dicT, HON2Rows) '3(粗利)
  215. End Sub
  216. 'ピボットシートから値を取得する
  217. Private Function GetValue(ByVal sheet_name, ByVal g_col As String, ByVal col1 As String, ByVal val1 As Variant, ByVal dicT As Object, ByRef TRows() As Long) As Variant
  218. Dim ix As Long
  219. Dim j, row, ctr As Long
  220. Dim gval As Variant 'PVシートから取得した集計対象値
  221. Dim gval1 As Variant 'PVシートから取得した条件値
  222. GetValue = Empty '取得値初期化
  223. '担当者のデータがないなら終了
  224. If dicT.exists(trg_key) = False Then Exit Function
  225. '担当者の添字とシート名を決定
  226. ix = dicT(trg_key)
  227. ctr = TRows(ix, 0)
  228. '該当する行の数ぶん繰り返す
  229. For j = 1 To ctr
  230. row = TRows(ix, j) '行番号取得
  231. '値を取得する
  232. gval = Workbooks(Uri_book).Worksheets(sheet_name).Cells(row, g_col).Value
  233. '取得値が空白でなく、かつ、取得条件が成立するなら、加算する
  234. If gval <> "" Then
  235. '取得したデータが数字でない場合は、エラー表示後、処理を打ち切る
  236. If IsNumeric(gval) = False Then
  237. MsgBox ("不正データ検出。以下のデータを正しく修正して下さい。処理を打ち切ります。")
  238. MsgBox ("ブック名[" & Uri_book & "] シート名(" & sheet_name & ")" & " 行番号=" & row & " 列=" & g_col)
  239. MsgBox (gval)
  240. Workbooks(Uri_book).Activate
  241. Workbooks(Uri_book).Worksheets(sheet_name).Activate
  242. Workbooks(Uri_book).Worksheets(sheet_name).Cells(row, g_col).Select
  243. End
  244. End If
  245. '条件の値を取得
  246. gval1 = Workbooks(Uri_book).Worksheets(sheet_name).Cells(row, col1).Text
  247. '条件が成立するなら加算する
  248. If gval1 = val1 Then
  249. GetValue = GetValue + gval
  250. End If
  251. End If
  252. Next
  253. End Function
  254. 'ピボットテーブル読み込み
  255. Private Sub readPivot(ByVal sheet_name As String, ByVal dicT As Object, ByRef TRows() As Long)
  256. Dim index As Long
  257. Dim sh As Worksheet
  258. Dim maxrow, row As Long
  259. Dim dmonth, key As String
  260. index = 0
  261. dmonth = trg_mm & "月"
  262. Set sh = Worksheets(sheet_name)
  263. maxrow = sh.Cells(Rows.count, "A").End(xlUp).row 'Sheet1 A列最大行
  264. '3行から最終行まで繰り返す
  265. For row = 3 To maxrow
  266. '集計月に一致するなら、テーブルに格納する(集計年は今のところ使用しない)
  267. If sh.Cells(row, "A").Text = dmonth Then
  268. '支店名+課名+担当者名
  269. key = sh.Cells(row, "D").Value & "|" & sh.Cells(row, "E").Value & "|" & sh.Cells(row, "C").Value
  270. Call add_table(sheet_name, dicT, TRows, index, row, key)
  271. End If
  272. Next
  273. End Sub
  274. 'テーブル登録
  275. Private Sub add_table(ByVal sheet_name As String, ByVal dicT As Object, ByRef TRows() As Long, ByRef index As Long, ByVal row, ByVal key As String)
  276. Dim i, j As Long
  277. If dicT.exists(key) = True Then
  278. i = dicT(key)
  279. j = TRows(i, 0)
  280. j = j + 1
  281. If j > Rmax Then
  282. MsgBox (sheet_name & "で1人のひと月の最大行数オーバー Rmaxを大きくしてください。Rmax=" & Rmax)
  283. End
  284. End If
  285. TRows(i, 0) = j
  286. TRows(i, j) = row
  287. Else
  288. If index > Pmax Then
  289. MsgBox (sheet_name & "で従業員の最大数オーバー Pmaxを大きくしてください。Pmax=" & Pmax)
  290. End
  291. End If
  292. dicT(key) = index
  293. TRows(index, 0) = 1
  294. TRows(index, 1) = row
  295. index = index + 1
  296. End If
  297. End Sub
  298. '指定月から指定月対応のカラム位置(計画数量)を計算する
  299. 'カラム位置は1からの連番
  300. '10月=4 ... 9月=184
  301. Private Function GetColNumber(ByVal mm As Long)
  302. Dim x, ix As Long
  303. If mm < 10 Then mm = mm + 12
  304. x = mm - 10
  305. ix = x + x \ 3 + x \ 6
  306. GetColNumber = 4 + 12 * ix
  307. End Function
  308. 'ピボット情報を出力する
  309. Private Sub OutPivot()
  310. Call OutPivotUnit("1部", HON1dicT, HON1Rows)
  311. Call OutPivotUnit("2部", HON2dicT, HON2Rows)
  312. Call OutPivotUnit("3部", HON3dicT, HON3Rows)
  313. End Sub
  314. '部単位でピボット情報を出力する
  315. Private Sub OutPivotUnit(ByVal sheetName As String, ByVal dicT As Object, ByRef TRows() As Long)
  316. Dim ws As Worksheet
  317. Dim key As Variant
  318. Dim row, col, ix, ctr, i, gno As Long
  319. ThisWorkbook.Activate
  320. Set ws = Worksheets(sheetName)
  321. ws.Cells.Clear
  322. row = 0
  323. '全てのキーを処理する
  324. For Each key In dicT
  325. ix = dicT(key)
  326. row = row + 1
  327. 'キー印字
  328. ws.Cells(row, 1).Value = key
  329. ctr = TRows(ix, 0)
  330. '行番号印字
  331. For i = 1 To ctr
  332. gno = TRows(ix, i)
  333. col = i + 1
  334. ws.Cells(row, col).Value = gno
  335. Next
  336. Next
  337. End Sub
  338.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty