fork download
  1. Option Explicit
  2. Const TRG_SHEET As String = "全体" '集計先シート名
  3. Const SRC_SHEET As String = "実績" '集計元シート名
  4. Const ROW_COUNT_OF_1BLOCK As Long = 28 '1ブロックの行数
  5. Const ROW_START_NO As Long = 6 'データの開始行
  6. Const ZENNEN As Long = 0 '前年
  7. Const TOUNEN As Long = 1 '当年
  8. Dim dicKCD As Object 'キー:分類区分コード 値:相対行番号(0オリジン)
  9. Dim dicRow As Object 'キー:開始行番号  値:true
  10. Dim dicT As Object 'キー:支店名+課名 値:開始行番号
  11. Dim srowAllSum As Long '全体合計の開始行
  12. Dim UriArray As Variant '売上集計対象 分類コード(82、86、85、87、88)
  13. Public Sub 新全体集計()
  14. Dim maxrow As Long
  15. Dim i As Long
  16. Dim j As Long
  17. Dim wrow As Long
  18. Dim wcol As Long
  19. Dim srow As Long '開始行
  20. Dim scol As Long '開始列
  21. Dim siten As String '支店名
  22. Dim ka As String '課名
  23. Dim key As Variant 'キー
  24. Dim t1 As Variant
  25. Dim t2 As Variant
  26. Dim ksh As Worksheet '管理シート
  27. Dim tsh As Worksheet '全体シート
  28. Dim zen_folder As String '前年フォルダー
  29. Dim tou_folder As String '当年フォルダー
  30. Dim zen_file As String '前年実績ファイル
  31. Dim tou_file As String '当年実績ファイル
  32. Dim block_count As Long '全体シートのブロック数
  33. Set dicKCD = CreateObject("Scripting.Dictionary")
  34. Set dicT = CreateObject("Scripting.Dictionary")
  35. Set dicRow = CreateObject("Scripting.Dictionary")
  36. Set tsh = Worksheets(TRG_SHEET)
  37. Set ksh = Worksheets("管理")
  38. UriArray = Array("82", "85", "86", "87", "88") '売上を集計する分類コード
  39. '管理シートのチェック
  40. zen_folder = ksh.Range("B2").Value
  41. tou_folder = ksh.Range("B3").Value
  42. zen_file = ksh.Range("C2").Value
  43. tou_file = ksh.Range("C3").Value
  44. Call check_folder("前年フォルダ", zen_folder)
  45. Call check_folder("当年フォルダ", tou_folder)
  46. Call check_file("前年ファイル", zen_folder & "\" & zen_file)
  47. Call check_file("当年ファイル", tou_folder & "\" & tou_file)
  48. '全体シートのチェック
  49. maxrow = tsh.Cells(Rows.Count, "C").End(xlUp).row 'C列の最終行を求める
  50. If (maxrow - ROW_START_NO + 1) Mod ROW_COUNT_OF_1BLOCK <> 0 Then
  51. MsgBox ("全体シートの行数不正")
  52. Exit Sub
  53. End If
  54.  
  55. 'ブロック数算出
  56. block_count = (maxrow - ROW_START_NO + 1) \ ROW_COUNT_OF_1BLOCK
  57.  
  58. '分類区分コードのリストを作成する
  59. For wrow = ROW_START_NO To (ROW_COUNT_OF_1BLOCK + ROW_START_NO - 1)
  60. key = CStr(tsh.Cells(wrow, "D").Value)
  61. If key <> "" Then
  62. If dicKCD.exists(key) = False Then
  63. dicKCD(key) = wrow - ROW_START_NO '相対行を記憶
  64. Else
  65. MsgBox ("全体シートの分類区分コード重複")
  66. Exit Sub
  67. End If
  68. End If
  69. Next
  70. 'ブロック開始行番号記憶
  71. For i = 1 To block_count '1~最後のブロックまで処理
  72. srow = GetRowNumber(i)
  73. dicRow(srow) = True
  74. Next
  75.  
  76. '全体シートの支店名・課名を記憶
  77. For wrow = ROW_START_NO To maxrow
  78. If tsh.Cells(wrow, "A").Value <> "" Then '支店名を取得
  79. siten = tsh.Cells(wrow, "A").Value
  80. End If
  81. If tsh.Cells(wrow, "B").Value <> "" Then '課名を取得
  82. ka = tsh.Cells(wrow, "B").Value
  83. End If
  84. If siten = "全体合計" Then '全体合計の記憶
  85. key = "|||合計"
  86. If dicT.exists(key) = False Then dicT(key) = wrow
  87. Else
  88. If Right(ka, 2) = "合計" Then '支店合計の記憶
  89. key = siten & "||合計"
  90. If dicT.exists(key) = False Then dicT(key) = wrow
  91. End If
  92. End If
  93. key = siten & "|" & ka
  94. If dicT.exists(key) = False Then
  95. If dicRow.exists(wrow) = False Then
  96. MsgBox ("開始行不正 行番号=" & wrow & " 支店=" & siten & " 課=" & ka)
  97. Exit Sub
  98. End If
  99. dicT(key) = wrow '行番号を記憶
  100. End If
  101. Next
  102. key = "|||合計"
  103. If dicT.exists(key) = False Then
  104. MsgBox ("全体合計が全体シートになし")
  105. Exit Sub
  106. End If
  107. srowAllSum = dicT(key)
  108. If MsgBox("集計を開始します", vbOKCancel) <> vbOK Then
  109. Exit Sub
  110. End If
  111.  
  112. t1 = Timer
  113. Application.ScreenUpdating = False
  114. Application.Calculation = xlCalculationManual
  115. '全体シートクリア
  116. For i = 1 To block_count '1~最後のブロックまで処理
  117. srow = GetRowNumber(i)
  118. For j = 1 To 12 '1月~12月まで処理
  119. scol = GetColNumber(j)
  120. Call blockClear(tsh, srow, scol)
  121. Next
  122. Next
  123. '前年データを集計
  124. Call Sum1Book(zen_folder, zen_file, ZENNEN)
  125. '当年データを集計
  126. Call Sum1Book(tou_folder, tou_file, TOUNEN)
  127. Application.ScreenUpdating = True
  128. Application.Calculation = xlCalculationAutomatic
  129. t2 = Timer
  130. MsgBox ("処理完了 所要時間(秒)=" & t2 - t1)
  131. End Sub
  132. Private Sub check_folder(ByVal comment As String, ByVal path As String)
  133. If Dir(path, vbDirectory) = "" Then
  134. MsgBox (comment & "が不正[" & path & "]は存在しません")
  135. End
  136. End If
  137. End Sub
  138. Private Sub check_file(ByVal comment As String, ByVal path As String)
  139. If Dir(path, vbNormal) = "" Then
  140. MsgBox (comment & "が不正[" & path & "]は存在しません")
  141. End
  142. End If
  143. End Sub
  144. '1つのブックを集計する
  145. Private Sub Sum1Book(ByVal src_folder As String, ByVal bookname As String, ByVal nendo As Long)
  146. Workbooks.Open src_folder & "\" & bookname
  147. Call Sum1Sheet(nendo)
  148. 'ブックを保存しないで閉じる(更新していないので保存不要)
  149. Workbooks(bookname).Saved = True
  150. Workbooks(bookname).Close
  151. End Sub
  152. '1つのシートを集計する
  153. Private Sub Sum1Sheet(ByVal nendo As Long)
  154. Dim ws As Worksheet
  155. Dim maxrow As Long
  156. Dim wrow As Long
  157. Dim wcol As String
  158. Dim mm As Long '月
  159. Dim siten As String '支店
  160. Dim ka As String '課
  161. Dim key As Variant '支店・課のキー
  162. Dim key2 As Variant '支店合計のキー
  163. Dim bcd As String '分類区分コード
  164. Dim val1 As Variant 'H列/I列の値
  165. Dim val2 As Variant 'J列の値
  166. Dim rowA As Long '全体シートの行
  167. Dim rowY As Long '全体シートの支店合計の行
  168. Dim rowZ As Long '全体シートの全体合計の行
  169. Dim scol As Long '全体シートの対応月の開始列
  170.  
  171. Set ws = Worksheets(SRC_SHEET)
  172. maxrow = ws.Cells(Rows.Count, "A").End(xlUp).row 'A列の最終行を求める
  173. For wrow = 3 To maxrow
  174. mm = get_month(ws.Cells(wrow, "A").Text)
  175. If mm = -1 Then
  176. Call abort_proc(nendo, wrow, "A", "売上日付不正(" & ws.Cells(wrow, "A").Text & ")")
  177. End If
  178. siten = ws.Cells(wrow, "B").Value '支店名取得
  179. ka = ws.Cells(wrow, "C").Value '課名取得
  180. key = siten & "|" & ka
  181. If dicT.exists(key) = False Then
  182. Call abort_proc(nendo, wrow, "B", "支店・課が全体シートに未登録(" & key & ")")
  183. End If
  184. key2 = siten & "||合計"
  185. If dicT.exists(key2) = False Then
  186. Call abort_proc(nendo, wrow, "B", "支店合計が全体シートに未登録(" & siten & ")")
  187. End If
  188. bcd = ws.Cells(wrow, "F").Value '分類区分コード取得
  189. If dicKCD.exists(bcd) = False Then
  190. Call abort_proc(nendo, wrow, "F", "分類区分コードが全体シートに未登録(" & bcd & ")")
  191. End If
  192. If is_uriage(bcd) = True Then
  193. wcol = "I"
  194. Else
  195. wcol = "H"
  196. End If
  197. val1 = get_val(nendo, ws, wrow, wcol)
  198. val2 = get_val(nendo, ws, wrow, "J")
  199. rowA = dicT(key) + dicKCD(bcd)
  200. rowY = dicT(key2) + dicKCD(bcd)
  201. rowZ = srowAllSum + dicKCD(bcd)
  202. scol = GetColNumber(mm)
  203. '数量/価格の集計
  204. Call add_val(nendo, rowA, scol + 3, val1)
  205. Call add_val(nendo, rowY, scol + 3, val1)
  206. Call add_val(nendo, rowZ, scol + 3, val1)
  207. '粗利の集計
  208. Call add_val(nendo, rowA, scol + 8, val2)
  209. Call add_val(nendo, rowY, scol + 8, val2)
  210. Call add_val(nendo, rowZ, scol + 8, val2)
  211. Next
  212. End Sub
  213. '全体シートへ加算する
  214. Private Sub add_val(ByVal nendo As Long, ByVal wrow As Long, ByVal wcol As Long, ByVal val As Variant)
  215. If val = "" Then Exit Sub
  216. If nendo = TOUNEN Then wcol = wcol + 1
  217. ThisWorkbook.Worksheets(TRG_SHEET).Cells(wrow, wcol).Value = ThisWorkbook.Worksheets(TRG_SHEET).Cells(wrow, wcol).Value + val
  218. End Sub
  219. '分類区分コードが売上の集計か否かを返す
  220. 'true:売上の集計
  221. 'false:数量の集計
  222. Private Function is_uriage(ByVal bcd As String) As Boolean
  223. Dim i As Long
  224. is_uriage = True
  225. For i = 0 To UBound(UriArray)
  226. If UriArray(i) = bcd Then Exit Function
  227. Next
  228. is_uriage = False
  229. End Function
  230. '文字で表示された月(1月...12月)の月を取得する
  231. Private Function get_month(ByVal mstr As String) As Long
  232. Dim mm As String
  233. get_month = -1
  234. If Right(mstr, 1) <> "月" Then Exit Function
  235. mm = Left(mstr, Len(mstr) - 1)
  236. If IsNumeric(mm) = False Then Exit Function
  237. get_month = CLng(mm)
  238. If get_month > 0 And get_month < 13 Then Exit Function
  239. get_month = -1
  240. End Function
  241. '指定行、指定列のデータの取得及びチェック
  242. Private Function get_val(ByVal nendo As String, ByVal ws As Worksheet, ByVal wrow As Long, ByVal wcol As String) As Variant
  243. get_val = ws.Cells(wrow, wcol).Value
  244. If IsNumeric(get_val) = False Then
  245. Call abort_proc(nendo, wrow, wcol, " 列=" & wcol & " 不正データ(" & ws.Cells(wrow, wcol).Text & ")")
  246. End If
  247. End Function
  248. 'マクロ停止処理
  249. Private Sub abort_proc(ByVal nendo As Long, ByVal wrow As Long, ByVal wcol As Variant, ByVal msg As String)
  250. Dim name As String
  251. If nendo = ZENNEN Then
  252. name = "前年元データ"
  253. Else
  254. name = "当年元データ"
  255. End If
  256. MsgBox (name & " 行番号=" & wrow & " " & msg)
  257. Worksheets(SRC_SHEET).Activate
  258. Cells(wrow, wcol).Select
  259. Application.Calculation = xlCalculationAutomatic
  260. End
  261. End Sub
  262. 'ブロッククリア(1課・1ケ月分)
  263. Private Sub blockClear(ByVal ws As Worksheet, ByVal srow As Long, ByVal scol As Long)
  264. Dim wrow As Long
  265. Dim key As Variant
  266. For Each key In dicKCD
  267. wrow = dicKCD(key) + srow
  268. ws.Cells(wrow, scol + 3).Value = ""
  269. ws.Cells(wrow, scol + 4).Value = ""
  270. ws.Cells(wrow, scol + 8).Value = ""
  271. ws.Cells(wrow, scol + 9).Value = ""
  272. Next
  273. End Sub
  274. '指定月から指定月対応のカラム位置(計画数量)を計算する
  275. 'カラム位置は1からの連番
  276. '10月=6 ... 9月=186
  277. Private Function GetColNumber(ByVal mm As Long)
  278. Dim x, ix As Long
  279. If mm < 10 Then mm = mm + 12
  280. x = mm - 10
  281. ix = x + x \ 3 + x \ 6
  282. GetColNumber = 6 + 12 * ix
  283. End Function
  284.  
  285. '指定ブロック番号の行番号を取得する
  286. '1=6,2=34,21=566
  287. Private Function GetRowNumber(ByVal blkNo As Long)
  288. GetRowNumber = ROW_START_NO + (blkNo - 1) * ROW_COUNT_OF_1BLOCK
  289. End Function
  290.  
  291. '列番号を英文字に変換
  292. Function ConvertToLetter(ByVal iCol As Integer) As String
  293. Dim iAlpha As Integer
  294. Dim iRemainder As Integer
  295. iAlpha = Int((iCol - 1) / 26)
  296. iRemainder = iCol - (iAlpha * 26)
  297. If iAlpha > 0 Then
  298. ConvertToLetter = Chr(iAlpha + 64)
  299. End If
  300. If iRemainder > 0 Then
  301. ConvertToLetter = ConvertToLetter & Chr(iRemainder + 64)
  302. End If
  303. End Function
  304.  
  305.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty