Board logo

標題: [發問] 將資料自動分類功能 [打印本頁]

作者: iceandy6150    時間: 2014-1-29 18:08     標題: 將資料自動分類功能

各位大大好
想請問一記帳功能,需求如下

工作表1:是輸入區     有---日期         項目  金額     人員    類別
                                      例:102/8/5    頭款   5000   小王    廠商
                                              102/8/7    貨款   2000   老李    公司
                                              102/8/9    出差   1000   小林    員工

工作表2:是歷史記錄,每天的工作表1的內容,要完整複製到工作表2存起來
                  而且不能蓋掉之前的紀錄。(可以的話,每天資料之間留兩列空白)

工作表3(含以後),是各類別項目單

如:
工作表3(廠商類),可放入10筆資料,如超過10筆,則需新開另一工作表(廠商類2)
                                 自動把工作表1中,類別為「廠商」的資料,複製到工作表3
                                 例:102/8/5    頭款   5000   小王    廠商

工作表4(公司類)。需求同工作表3。自動把工作表1中,類別為「公司」的資料,複製到工作表4

工作表5(員工類)。需求同工作表3。自動把工作表1中,類別為「員工」的資料,複製到工作表5

<工作表3~5只有每天使用,列印後就可以了,可清空舊資料>



因為目前工作表1,2都是手動輸入。工作表3~5,要每個資料從工作表1中,人工分類複製貼到各工作表去
如果有大大知道怎麼設定,或使用按鈕讓程式自己跑
將可節省很多時間
請各位指導,感謝!
作者: iceandy6150    時間: 2014-1-29 23:35

我想所需功能大概分兩部分
一是在工作表2由上而下找到空白可用處,再把工作表1的資料複製過來
二是去判斷類別,再將資料複製到各工作表

首先由上而下找到空白我寫不太出來
一直說有錯
Private Sub CommandButton1_Click()
Dim i As Integer
i = 1

Do
      If Worksheets("工作表2").Range(Cells(i, 1), Cells(i, 7)) = "" Then
      MsgBox (i)                 '顯示第i行是完全空白,表示可用
      Exit Do
      End If
i = i + 1
Loop

End Sub

我想做到逐列尋找(用i來做)
然後一個範圍內都是空白,語法不會寫,range()從第i列的第1欄到第7欄都空白就表示已經到底
若其中一欄非空白,就i=i+1繼續找下去

可是遇到瓶頸了
希望有大大能解答
謝謝
作者: GBKEE    時間: 2014-1-30 14:09

回復 2# iceandy6150
  1. Option Explicit
  2. Sub Ex()
  3.     Dim i As Integer, Sh As Worksheet
  4.     Application.DisplayAlerts = False
  5.     For Each Sh In Sheets
  6.         If Sh.Name <> "工作表1" And Sh.Name <> "工作表2" Then Sh.Delete
  7.         '活頁簿只留 工作表1:是輸入區,工作表2:是歷史記錄
  8.     Next
  9.     With Sheets("工作表2")
  10.         If .UsedRange.Rows.Count = 1 Then               '沒有歷史紀錄
  11.             Sheets("工作表1").UsedRange.Copy            '複製(含標頭)
  12.             .Range("a1").PasteSpecial xlPasteValues
  13.         Else
  14.             Sheets("工作表1").UsedRange.Offset(1).Copy  '複製(不含標頭)
  15.             .Range("A" & .UsedRange.Rows.Count).Offset(3).PasteSpecial xlPasteValues
  16.             'Offset(3) :空2列->第3列貼上
  17.         End If
  18.         .UsedRange.Range("E:E").AdvancedFilter xlFilterCopy, , .Cells(1, .Columns.Count), True
  19.         '進階篩選 E欄 不重複資料到工作表最右欄 ***取得類別的分類***
  20.         i = 2
  21.         .Cells(1, .Columns.Count - 1) = .UsedRange.Range("E1")    '進階篩選的欄位名稱是E欄的標頭
  22.         Do While .Cells(i, .Columns.Count) <> ""                  '工作表最右欄的儲存格 <>""
  23.             Set Sh = Sheets.Add(, Sheets(Sheets.Count))           '新增的類別工作表
  24.             Sh.Name = .Cells(i, .Columns.Count)
  25.             .Cells(2, .Columns.Count - 1) = Sh.Name
  26.            .UsedRange.AdvancedFilter xlFilterCopy, .Cells(1, .Columns.Count - 1).Resize(2), Sh.[a1], True
  27.            '工作表2 進階篩選 準則[分類]="工作表1"最右欄的儲存格, 複製到新增的類別工作表[A1]
  28.            Do While Sh.UsedRange.Rows.Count > 11                  '資料列>11列
  29.                 Sh.Copy , Sheets(Sh.Index)                        '1 原工作表複製
  30.                 Sh.Rows("11:" & Sh.Rows.Count).Delete             '2 原工作表刪除11列以下的資料(保持10列)
  31.                 Set Sh = ActiveSheet                              '3 複製的工作表 指定給變數
  32.                 Sh.Rows("2:11").Delete                            '4 複製的工作表刪除2:11列的資料
  33.            Loop
  34.            i = i + 1
  35.         Loop
  36.         .Cells(1, .Columns.Count).CurrentRegion = ""
  37.     End With
  38. End Sub
複製代碼

作者: iceandy6150    時間: 2014-1-31 11:10

回復 3# GBKEE


    感謝GBKEE大大的回覆,功能正常,除了一些小問題

1:Option Explicit 程式跟我說有問題,加上'當成註解後,運作正常

2:我的需求有點小出入
      (1)我其他的工作表(3~5)因為有畫好表格(單子),所以不能刪除
           只能把工作表1的資料複製、貼進去
          (每張表格只能填10筆資料,所以超過10筆才要另開新表,原因在此)

           我想是不是把下列程式刪除?
           For Each Sh In Sheets
            If Sh.Name <> "工作表1" And Sh.Name <> "工作表2" Then Sh.Delete
            '活頁簿只留 工作表1:是輸入區,工作表2:是歷史記錄
            Next

             改成,把工作表3~5裡面的舊資料清空,例如A5~E14=""
  
        (2)在挑選類別的時候,例如有好幾筆
            第1筆, 如果是員工類,就放到"員工"工作表,A5~E5  (單子第1筆)
            第2筆, 如果是員工類,就放到"員工"工作表,A6~E6 (單子第2筆)
            第3筆, 如果是員工類,就放到"員工"工作表,A7~E7  (單子第3筆)
            第4筆, 如果是公司類,就放到"公司"工作表,A5~E5  (單子第1筆)
            第5筆, 如果是廠商類,就放到"廠商"工作表,A5~E5  (單子第1筆)
            第6筆, 如果是公司類,就放到"公司"工作表,A6~E6  (單子第2筆)
            第7筆, 如果是公司類,就放到"公司"工作表,A7~E7  (單子第3筆)
            以此類推,

            至於超過10筆就開新工作表部分,功能均正常,我再稍微修改即可

以上,感謝
作者: iceandy6150    時間: 2014-1-31 14:00

  1. Private Sub CommandButton1_Click()
  2. 'Option Explicit    (刪除)

  3. 'Sub Ex()   (刪除)

  4.     Dim i As Integer, Sh As Worksheet

  5.     Application.DisplayAlerts = False

  6.     For Each Sh In Sheets

  7.         If Sh.Name <> "工作表1" And Sh.Name <> "工作表2" Then      'Sh.Delete   (把刪掉工作表的動作取消)

  8.         '活頁簿只留 工作表1:是輸入區,工作表2:是歷史記錄
  9.         
  10.         Sh.Range("A2:E11").Value = ""     '(自己加上清除其餘工作表中,特定範圍清空資料的功能)
  11.             
  12.         End If

  13.     Next

  14.    
  15.     With Sheets("工作表2")

  16.         If .UsedRange.Rows.Count = 1 Then               '沒有歷史紀錄

  17.             Sheets("工作表1").UsedRange.Copy            '複製(含標頭)

  18.             .Range("a1").PasteSpecial xlPasteValues

  19.         Else

  20.             Sheets("工作表1").UsedRange.Offset(1).Copy  '複製(不含標頭)

  21.             .Range("A" & .UsedRange.Rows.Count).Offset(3).PasteSpecial xlPasteValues

  22.             'Offset(3) :空2列->第3列貼上

  23.         End If

  24.         .UsedRange.Range("E:E").AdvancedFilter xlFilterCopy, , .Cells(1, .Columns.Count), True

  25.         '進階篩選 E欄 不重複資料到工作表最右欄 ***取得類別的分類***

  26.         i = 2

  27.         .Cells(1, .Columns.Count - 1) = .UsedRange.Range("E1")    '進階篩選的欄位名稱是E欄的標頭

  28.         Do While .Cells(i, .Columns.Count) <> ""                  '工作表最右欄的儲存格 <>""

  29.             'Set Sh = Sheets.Add(, Sheets(Sheets.Count))           '新增的類別工作表     (這邊不新增工作表,故刪除)

  30.             'Sh.Name = .Cells(i, .Columns.Count)                           ' (這邊不新增工作表,故刪除)

  31.             '.Cells(2, .Columns.Count - 1) = Sh.Name                   ' (這邊不新增工作表,故刪除)

  32. '這邊應該要加入,判斷為哪一類別,並把該列資料複製到那個類別的工作表去,但我不會寫,是下面這行?

  33.            .UsedRange.AdvancedFilter xlFilterCopy, .Cells(1, .Columns.Count - 1).Resize(2), Sh.[a1], True    '左邊這行除錯說沒有WITH,但明明就有,好怪

  34.            '工作表2 進階篩選 準則[分類]="工作表1"最右欄的儲存格, 複製到新增的類別工作表[A1]

  35.            Do While Sh.UsedRange.Rows.Count > 11                  '資料列>11列

  36.                 Sh.Copy , Sheets(Sh.Index)                        '1 原工作表複製

  37.                 Sh.Rows("11:" & Sh.Rows.Count).Delete             '2 原工作表刪除11列以下的資料(保持10列)

  38.                 Set Sh = ActiveSheet                              '3 複製的工作表 指定給變數

  39.                 Sh.Rows("2:11").Delete                            '4 複製的工作表刪除2:11列的資料

  40.            Loop

  41.            i = i + 1

  42.         Loop

  43.         .Cells(1, .Columns.Count).CurrentRegion = ""

  44.     End With

  45. 'End Sub  (原本的,刪除)
  46. End Sub
複製代碼
回復 4# iceandy6150

我修改了一下大大的程式
可是卡住不能運作了
作者: iceandy6150    時間: 2014-1-31 18:20

回復 5# iceandy6150


    已附加檔案
     工作表1如果按鈕不小心按到兩次
     會複製兩次到工作表2
     其餘工作表的表格我簡化過,跟正本差一些而已
      謝謝
作者: iceandy6150    時間: 2014-1-31 18:57

補充一下,實際上類別不止三種,可能高達十多種,我範例是舉三例
另外每一類別的工作表我可以手動建立
萬一後面又要再多新的類別,我也可以慢慢增加

要搜尋類別,我是想到兩種方式
1.是用CASE,把會用到的都先內建,再把各類編號
    IF 工作表1.類別.cells().value = "公司" then k=1
    IF 工作表1.類別.cells().value = "員工" then k=2
    以此類推
   然後CASE(K)做判斷  去做複製、貼過去的動作

2.設一變數A = 工作表1的第i筆資料的類別的值  (例如是公司)
   再逐一找工作表的名稱,看是否與A一樣,若一樣則去做複製、貼過去的動作
For Each Sh In Sheets
        If Sh.Name = A then  做複製、貼過去的動作
        end if
next

不曉得這樣行不行得通?
謝謝
作者: GBKEE    時間: 2014-2-1 07:22

本帖最後由 GBKEE 於 2014-2-1 10:00 編輯

回復 7# iceandy6150

試試看
作者: iceandy6150    時間: 2014-2-2 23:54

回復 8# GBKEE

GBKEE版大您好

試了一下您的檔案後,問題如下

一、    With Sheets("工作表2")
        If .UsedRange.Rows.Count = 1 Then              '沒有歷史紀錄
        這一行無論有沒有資料都無法執行,就直接跳ELSE那一塊了
        所以我改成
        If .Cells(1, 1).Value = "" Then       功能相同

二、篩選及建立類別工作等工作,所用到的資料應該是輸入區(工作表1)的資料
       所以我多加了end with
      再多加 With Sheets("工作表1"),讓篩選及建立類別工作等工作正常運作

三、    Else
            Sheets("工作表1").UsedRange.Offset(1).Copy  '複製(不含標頭)
            .Range("A" & .UsedRange.Rows.Count).Offset(3).PasteSpecial xlPasteValues
            'Offset(3) :空2列->第3列貼上
            
             這邊的 .Range("A" & .UsedRange.Rows.Count)老是會算錯
            嚴格來說是.UsedRange.Rows.Count會出錯
            我特地加兩行程式,顯示一下到底算出幾列來
            k = Sheets("工作表2").UsedRange.Rows.Count
           MsgBox (k)
           結果工作表2只有7列,程式跑出:已使用26列

           我不死心,於是在工作表2弄了一個按鈕
           一樣的程式跑看看已使用的列數,秀出來
           還是一樣已使用26,明明都是空白,我不知道為什麼
           但是拿來算工作表1就很正確

我上傳我修改後的檔案
目前狀態是,工作表1已經輸入一次資料,按了一次按鈕
所以產生了該產生的其他類別工作表
也把工作表1該複製的資料,都貼到工作表2了

工作表1裡面,是輸入好第2次的資料,但還沒按按鈕
(因為貼的動作會錯<.UsedRange.Rows.Count會出錯>)

再麻煩幫我看看問題出在哪裡
謝謝
作者: GBKEE    時間: 2014-2-3 07:19

回復 9# iceandy6150
請看看 Sheets("工作表2")最右邊的IV欄
作者: iceandy6150    時間: 2014-2-3 09:24

回復 10# GBKEE


    感謝GBKEE版大提醒,也很奇怪為什麼工作表2最右邊會有東西
    再回頭去看工作表1最右邊也有東西,難怪一直出錯
    都刪掉後,所有功能正常運作
    感謝再感謝
作者: GBKEE    時間: 2014-2-3 09:46

回復 11# iceandy6150
須多了解程式碼的意義
我的是Sheets("工作表2") 你改為 Sheets("工作表1")
  1. With Sheets("工作表1")'
  2.     .UsedRange.Range("E:E").AdvancedFilter xlFilterCopy, , .Cells(1, .Columns.Count), True
  3.     'AdvancedFilter:進階篩選
  4.    'xlFilterCopy:進階篩選的資料顯示在其他地方
  5.    '.Cells(1, .Columns.Count) ->工作表的最右欄第1個儲存格->進階篩選的資料顯示的地方
複製代碼

作者: iceandy6150    時間: 2014-2-3 10:23

回復 12# GBKEE

原來那一行的意思是這樣呀
多謝G大講解

但是原本G大的程式,會將工作表2裡面的所有歷史資料去做動作 (新增類別工作表...等)
而我原本要做的是,工作表1是輸入區,針對輸入區的資料去做動作
工作表2純粹是存資料用的
工作表1可能每天要用個1~3次,工作表2只是紀錄每天的項目

第1次我可能輸入10筆,按下按鈕,產生兩類的工作表,列印當收據後就OK
第2次我可能輸入35筆,按下按鈕,產生五類的工作表,每一類列印後就OK
第3次我可能輸入3筆,按下按鈕,產生一類的工作表,這一類列印後就OK
而工作表2則是記錄這48筆資料,方式是10筆後空兩行,再35筆後空兩行,再3筆

那請問G大, .UsedRange.Range("E:E").AdvancedFilter xlFilterCopy, , .Cells(1, .Columns.Count), True
這一行還是要放在工作表2囉?   讓篩選出來的分類會放到工作表2的IV欄
但是這樣,下面要產生新的類別工作表的程式,我放在工作表1,又會找不到篩選出來的分類
怎麼改比較好呢?

應該是這行要改,但我不會改成指定去找工作表2的IV欄
For Each Ar In .AutoFilter.Range.SpecialCells(xlCellTypeVisible).Rows  '篩選出的資料列
作者: iceandy6150    時間: 2014-2-3 11:06

回復 13# iceandy6150

G大,我發現一點了
進階篩選放在Sheets("工作表1")是可以的
當我在工作表1輸入好資料後,按下按鈕

透過下面這一行
.UsedRange.Range("E:E").AdvancedFilter xlFilterCopy, , .Cells(1, .Columns.Count), True  
可以篩選出有多少類別,並顯示在"工作表1的最右欄"

然後
就會去做產生新的工作表(改名字,變成類別名)
然後把該類的資料逐一放入

都好了以後,應該要清除<工作表1的最右欄>
那我也發現G大寫得程式中有下面這一行
.Cells(1, .Columns.Count).CurrentRegion = ""
但是這一行只把最近用到的類別給清掉

例如依序產生了  公司-->廠商-->內部-->員工這四類
就只會清掉員工
等程式跑完,會在<工作表1的最右欄>殘存公司、廠商、內部
如果那一行的指令可以完全清除<工作表1的最右欄>的所有東西
那一切就沒問題了!

再請G大幫忙解答,謝謝
作者: iceandy6150    時間: 2014-2-3 11:23

  1. Option Explicit   '必須置於模組頂端 強制宣告變數
  2. Private Sub CommandButton1_Click()
  3.     Dim Sh As Worksheet, i As Integer, ii As Integer, r As Integer, Ar 'Dim 宣告變數
  4.     Dim k As Integer
  5.    
  6.     Application.DisplayAlerts = False
  7.     Application.ScreenUpdating = False
  8.     For Each Sh In Sheets
  9.         If Sh.Name <> "工作表1" And Sh.Name <> "工作表2" And Sh.Name <> "表格範本" Then Sh.Delete
  10.         '活頁簿只留 工作表1:是輸入區,工作表2:是歷史記錄 ,"表格範本"
  11.     Next
  12.    
  13.     With Sheets("工作表2")
  14.         If .UsedRange.Rows.Count = 1 Then              '沒有歷史紀錄
  15.            '.UsedRange.Rows.Count = 1

  16.              Sheets("工作表1").UsedRange.Copy            '複製(含標頭)
  17.             .Range("A1").PasteSpecial xlPasteValues
  18.             
  19.         Else
  20.             Sheets("工作表1").UsedRange.Offset(1).Copy  '複製(不含標頭)
  21.             Sheets("工作表2").Range("A" & .UsedRange.Rows.Count).Offset(3).PasteSpecial xlPasteValues
  22.             'Offset(3) :空2列->第3列貼上
  23.            
  24.         End If
  25.         

  26.         
  27.     End With
  28.    
  29.    
  30.     With Sheets("工作表1")
  31.    
  32.     .UsedRange.Range("E:E").AdvancedFilter xlFilterCopy, , .Cells(1, .Columns.Count), True
  33.     '進階篩選 E欄 不重複資料到工作表最右欄 ***取得類別的分類***
  34.     'AdvancedFilter:進階篩選
  35.     'xlFilterCopy:進階篩選的資料顯示在其他地方
  36.     '.Cells(1, .Columns.Count) ->工作表的最右欄第1個儲存格->進階篩選的資料顯示的地方
  37.         
  38.         i = 2
  39.         Do While .Cells(i, .Columns.Count) <> ""                  '工作表最右欄的儲存格 <>""
  40.             .Range("A:E").AutoFilter 5, .Cells(i, .Columns.Count)          'AutoFilter: 自動篩選 ,第5欄(類別)的準則為 .Cells(i, .Columns.Count)
  41.             Sheets("表格範本").Copy , Sheets(Sheets.Count)
  42.             Set Sh = ActiveSheet
  43.             Sh.[a1] = .Cells(i, .Columns.Count) & "支出表"
  44.             Sh.Name = .Cells(i, .Columns.Count)
  45.             r = 5
  46.             For Each Ar In .AutoFilter.Range.SpecialCells(xlCellTypeVisible).Rows  '篩選出的資料列
  47.                 If r = 17 Then
  48.                     r = 6
  49.                     Sh.Copy , Sheets(Sheets.Count)
  50.                     Set Sh = ActiveSheet
  51.                     Sh.Range("A6:E16") = ""
  52.                 End If
  53.                 Sh.Cells(r, "a").Resize(, Ar.Columns.Count) = Ar.Value   'Index(AR, ii) :讀取陣列
  54.                 r = r + 1
  55.            Next
  56.            i = i + 1
  57.         Loop
  58.         
  59.         k = 1
  60.         Do While .Cells(k, .Columns.Count) <> ""
  61.         .Cells(k, .Columns.Count) = ""
  62.         k = k + 1
  63.         Loop
  64.         
  65.         '.Cells(1, .Columns.Count).CurrentRegion = ""
  66.         .AutoFilterMode = False
  67.     End With
  68.     Application.ScreenUpdating = True
  69.     Me.Activate
  70. End Sub
複製代碼
回復 14# iceandy6150

我試出來了,貼上代碼及附檔
感謝G大熱心教學

只要在工作表1,輸入資料,按下按鈕,就能自動產生相對應的工作表
並將資料分類好放到相對應的工作表內,可供使用者直接列印出來
而每次動作也會記錄在工作表2中,當作歷史紀錄
作者: iceandy6150    時間: 2014-2-3 17:09

回復 15# iceandy6150

G版大,不好意思又來發問了,發現與實際應用有點落差

[attach]17409[/attach]
首先是圖中紅色部分
1.第一個紅框裡的東西和工作表表名是一樣的
而且要怎麼設定一個內放兩行,我不會

2.問題比較大的是右邊的紅框
因為每一類工作表它的字號不一樣
可能是庶字008號、013號,而且沒啥規則可言
在產生新的工作表時,還要兼顧裡面字號是否正確
   
3.三個藍框是要從輸入區複製資料過來貼上
    並不是整列的資料都貼

4.綠框是合計,可以的話直接程式寫好,產生新工作表就已有
   或是再自己手動設定也行

5.右下兩個黃框,sheet1就是輸入區,也就是範例的工作表1
   總表,也就是歷史資料區,範例的工作表2

6.圖片正下方可以看到,種類超多的,並有各自的代號

接下來看一下總表的部分,(也就是歷史資料),我貼一部分上來

[attach]17410[/attach]

1.總共有7個欄位:序號、日期、物品、對象、金額、敘述、類別

2.圖中紅框1.2.3放到各類別工作表中,順序卻不一樣,變2.3.1中間還有空格

目前打算是這樣
SHEET1就是輸入區,長得就跟<總表>一樣的順序
所以要複製貼上會比較方便

但如果要用G大您寫好的程式去改
可能還要用一個工作表,裡面放參考值,比如說
類別為[一般事務費],那sh.name就是[一般事務費279],字號為[庶字第016號]
以此類推
把每一類別都打好,讓程式參照,以便新產生工作表時可以正確套用

還是有別的好方法?

另外一條路,就是在sheet1(輸入區),逐一列判斷為哪一類
再做複製、貼上到該類工作表去的動作
(如同原本舊方法,建立好各類工作表,有資料才貼進來
沒資料就空著不動)
這樣是不用顧慮到各類工作表的字號不同問題

該怎麼辦呢?
請再幫我想想,謝謝
作者: iceandy6150    時間: 2014-2-3 23:52

回復 16# iceandy6150

請問版上各位大大
一張工作表中,我只想針對某個範圍下程式,有語法嗎?

例如,我想判斷工作表1中的D7:J19這個範圍,已經被使用過的列有幾列
(不要判斷整張工作表)
該怎麼寫語法?

Private Sub CommandButton1_Click()
    Dim myRgn As Range
    Dim a As Integer
    Set myRgn = Range("D7:J19")
    ThisWorkbook.Names.Add "DataRange", myRgn
'(以上是網路看來的)   

    With Sheets("工作表1")
        
         With Range("DataRange")
         a = .UsedRange.Rows.Count
         End With
         
    End With
   
    MsgBox (a)
      
End Sub

可是都跟我說程式不對
求救一下,謝謝
作者: GBKEE    時間: 2014-2-4 07:45

本帖最後由 GBKEE 於 2014-2-4 09:35 編輯

回復 17# iceandy6150
  1. With Sheets("工作表1")  '工作表物件才有UsedRange物件   
  2.          With .Range("DataRange")  ' 沒有UsedRange
  3.          'a = .UsedRange.Rows.Count '
  4.           MsgBox Application.CountA(.Columns(1)) '指定"DataRange"第一欄->使用的列數
  5.        ' Application.CountA : VBA中使用工作表函數 CountA  
  6.        MsgBox Application.CountA(.Cells)      '"DataRange"範圍內
  7.          End With         
  8.     End With
複製代碼
15#
  1. 'k = 1
  2.         'Do While .Cells(k, .Columns.Count) <> ""
  3.         '.Cells(k, .Columns.Count) = ""
  4.         'k = k + 1
  5.         'Loop
  6.         .Cells(k, .Columns.Count).EntireColumn = ""    'EntireColumn :整欄
  7.         '.Cells(1, .Columns.Count).CurrentRegion = ""  'CurrentRegion:連續的資料範圍
複製代碼
16# 檔案的私密資料遮蔽,上傳看看
作者: iceandy6150    時間: 2014-2-4 11:02

回復 18# GBKEE

G版大您好
我將實際要用的檔案上傳,部分資料已蓋掉

原本使用者是將要輸入的資料直接打進<總表>
再將各類別的工作表所需要的儲存格設定 =總表的D7  (舉例)
但是每次總表一改,資料一增加,就又要去該類工作表設定  =總表的D28  (舉例)
於是我想寫程式改善,不用每次都去改

如果程式能自動判斷該筆資料是屬於哪一類,就自動貼過去那一類的工作表
就簡單多了
可是如果程式判斷的是<總表>,很難分辨哪些是舊的,哪些是這次要用的
於是繞一條路,用一個輸入區<sheet1> (也就是發問範例的<工作表1>)
讓程式判斷<輸入區>的資料,並做分類及貼過去的動作
再將本次資料複製貼到<總表>去

G大您的作法是,利用產生新表的方式

我原本是想說,程式跑的時候
1.先從<輸入區>複製、貼過去<總表>,空兩列(為了支票號碼要用)(這手動設定)
   逐工作表內的區域清空舊資料 (保留表格及格式,要放資料的地方清空就好)

2.逐列判斷<輸入區>,若A類,sheetA選擇,判斷特定範圍是否還有空格,放入資料,
   (所以我才要問怎麼判斷工作表中,特定範圍已使用的列數,才能知道是否還有空格)
   若滿了,複製sheetA,清空,改名sheetA(2),放入剩餘資料(這部分發問的範例已解答)

我想兩種方法應該都可以做到相同結果
只是我比較不熟
所以請G大及版上高手們看看
幫小弟想一下解決方法
謝謝

[attach]17418[/attach]
作者: GBKEE    時間: 2014-2-4 11:55

本帖最後由 GBKEE 於 2014-2-4 14:43 編輯

回復 19# iceandy6150
附檔上總表G欄類別沒數字, 但工作表[保險231],[通訊203]..有數字 這些工作表的命名規則你沒說明!
[總表]資料可在H欄加註辨別新舊資料
16# 可能還要用一個工作表,裡面放參考值,比如說 類別為[一般事務費],那sh.name就是[一般事務費279],字號為[庶字第016號]
庶字第016號 在何處??
請告知疑惑,程式才寫的下去.
作者: iceandy6150    時間: 2014-2-4 23:27

回復 20# GBKEE

A-附檔上總表G欄類別沒數字, 但工作表[保險231],[通訊203]..有數字 這些工作表的命名規則你沒說明!
     [總表]資料可在H欄加註辨別新舊資料
     16# 可能還要用一個工作表,裡面放參考值,比如說 類別為[一般事務費],那sh.name就是[一般事務費279],字號為[庶字第016號]
B-庶字第016號 在何處??
   
G大,關於問題A,因為原本是人工處理,<總表>中的G欄只會看到類別,不會有數字
比方說<總表>裡面[類別]打的是[保險],人眼一看就知道要去找工作表<保險231>
然後把<保險231>裡面第一列D7,設定成    =總表!D48  (設定成在總表中的位置)
這樣就可以把<總表>的資料對應到<保險231>中
萬一有第2.3.4...筆資料,還得人工逐一設定成   =總表!D??

所以,可能也沒什麼命名規則,因為我也不知道為什麼保險要用231,通訊要用203,真的很抱歉
我只是好心幫忙,想說把人工處理的部分,利用程式做完而已

關於問題B,就在每個工作表的I3裡面,("零用金清單"這幾個字的右下方)
與問題A同,好像也沒規則可言,我每個類別點來點去,發現是不一樣的字號
往前幾個回文,我有貼圖片,裡面也可看到

感恩,謝謝
作者: yen956    時間: 2014-2-5 00:08


試試看:
VBA code:
Option Explicit

Sub 清除資料()
    Dim i, msg As Integer, x, sh As Worksheet
    Set x = Sheets("輸入")
    Application.DisplayAlerts = False
   
    '若將工作頁命名為 "輸入","歷史","廠商類","員工類","公司類","廠商類(1)","廠商類(2)",...
    '則可依 Len(Sh.Name) 決定 Delete 或 Clearcontents
    For Each sh In Sheets
        If Len(sh.Name) > 3 Then
           sh.Delete
        ElseIf Len(sh.Name) = 3 Then
           sh.Range("A2:E11").ClearContents
        End If
    Next
   
    '清除篩選區的資料
    x.Range("G:K").Clear
   
    '是否清除輸入區的資料?
    msg = MsgBox("要清除輸入區的資料嗎?", vbYesNo)
    If msg = vbYes Then
       x.Range("A2:E" & x.UsedRange.Rows.Count).ClearContents
    End If
End Sub
   
Sub 存入歷史紀錄()
    Dim i, msg As Integer, sh, x, y As Worksheet
    Dim 舊日期, 新日期 As Date
    Set x = Sheets("輸入")
    Set y = Sheets("歷史")
    Application.ScreenUpdating = False
   
    '如果尚未有歷史紀錄(第一次), 從 "輸入" 複製到 "歷史" (含標頭)
    If y.UsedRange.Rows.Count = 1 Then
        x.Range("A1:E" & x.UsedRange.Rows.Count).Copy
        y.Range("A1").PasteSpecial xlPasteValues
    Else
        舊日期 = y.Range("A" & y.UsedRange.Rows.Count)
        新日期 = x.Range("A" & x.UsedRange.Rows.Count)
        
        '注意:"輸入"頁 A欄(即日期欄), 應設定 資料驗証, 並設為 "日期",
        '否則 If 舊日期 < 新日期 Then 會判斷錯誤!!
        '從 "輸入"頁 複製到 "歷史"頁 (不含標頭, 且空2列)
        If 舊日期 < 新日期 Then
            x.Range("A2:E" & x.UsedRange.Rows.Count).Copy
            y.Range("A" & y.UsedRange.Rows.Count + 3).PasteSpecial xlPasteValues
        Else
            msg = MsgBox(DateValue(新日期) & " 已經存過了!!", vbOKOnly)
        End If
    End If
    Application.ScreenUpdating = True
End Sub

Sub 篩選資料()
   Dim i, UsedRow As Integer, x, sh, shOld As Worksheet
   Dim shName
   shName = Array("廠商類", "公司類", "員工類")
   Set x = Sheets("輸入")
   Application.DisplayAlerts = False
   Application.ScreenUpdating = False
   
   '因為 "廠商類"、"公司類"、"員工類" 只有每天使用,
   '列印後就可以清空舊資料, 故應依 "輸入" 篩選, 而不是依 "歷史"
   For i = 0 To 2
      Set sh = Sheets(shName(i))
      x.Activate
      
      '將進階篩選的 篩選準則 填入 x.[F3]
      x.[F3] = Left(shName(i), 2)
      
      '進階篩選 A:E欄 重複資料到 "G1"       ***測試用(多筆重複)***
      x.Range("A1:E" & x.UsedRange.Rows.Count).AdvancedFilter xlFilterCopy, x.Range("F2:F3"), x.Range("G1:K1"), False
            
      '進階篩選 A:E欄 不重複資料到 "G1"     ***實際用(不重複)***
      'x.Range("A1:E" & x.UsedRange.Rows.Count).AdvancedFilter xlFilterCopy, x.Range("F2:F3"), x.Range("G1:K1"), True
            
      '將 篩選結果 複製到對應的類別工作表
      x.Range("G:K").Copy
      sh.[A1].PasteSpecial xlPasteValues
         
      Do While sh.[A12] <> ""                    '直到對應的類別工作表[A12] = ""
         sh.Copy After:=Sheets(Sheets.Count)                 '1 複製原工作表
         sh.Rows("12:" & sh.Rows.Count).Delete               '2 將原工作表12列以下刪除(保留10列)
         Set shOld = sh                                      '3 將 shOld 設給原工作表
         Set sh = Sheets(Sheets.Count)                       '4 將 sh 設給新工作表
         sh.Rows("2:11").Delete                              '5 刪除新工作表 2:11 列
         shOld.[A1:E11].Copy                                 '6 複製原工作表的 格式 到新工作表
         sh.[A1].PasteSpecial xlPasteFormats
      Loop
   Next
   Application.ScreenUpdating = True
End Sub
作者: yen956    時間: 2014-2-5 00:34

抱歉, 沒一直看到最後一頁就回覆,
就當沒回覆這一回事, 抱歉!!
補圖(頁碼部份):

作者: GBKEE    時間: 2014-2-5 10:13

回復 21# iceandy6150
沒有規律性那你就用手動
  1. Option Explicit   '必須置於模組頂端 強制宣告變數
  2. Sub Ex()
  3.     Dim i As Integer, Sh As Worksheet, Rng As Range, xRow As Range, R As Integer
  4.     With Sheets("總表")
  5.         If .UsedRange.Rows.Count = 1 Then              '沒有歷史紀錄
  6.            Sheets("Sheet1").UsedRange.Copy            '複製(含標頭)
  7.             .Range("A1").PasteSpecial xlPasteValues
  8.         Else
  9.             Sheets("Sheet1").UsedRange.Offset(1).Copy  '複製(不含標頭)
  10.             .Range("A" & .UsedRange.Rows.Count).Offset(3).PasteSpecial xlPasteValues
  11.             'Offset(3) :空2列->第3列貼上
  12.         End If
  13.     End With
  14.     With Sheets("SHEET1")  '工作表:輸入區
  15.         .Range("A1").CurrentRegion.Range("G:G").AdvancedFilter xlFilterCopy, , .Cells(1, .Columns.Count), True
  16.         i = 2
  17.         Do While .Cells(i, .Columns.Count) <> ""
  18.             .Range("A1").AutoFilter 7, .Cells(i, .Columns.Count)         '自動篩選
  19.             Set Sh = Sheets(類別表(.Cells(i, .Columns.Count)))           '指定到類別的工作表
  20.             For Each xRow In .AutoFilter.Range.SpecialCells(xlCellTypeVisible).Rows '自動篩選範圍列的集合
  21.                 If xRow.Row > 1 Then
  22.                      R = Application.CountA(Sh.[D7:D19])                 '有輸入的資料數
  23.                      With Sh.[D7].Offset(R)
  24.                         .Cells(, 1) = xRow.Range("D1")
  25.                         .Cells(, 5) = xRow.Range("F1")
  26.                         .Cells(, 7) = xRow.Range("E1")
  27.                      End With
  28.                      If Application.CountA(Sh.[D7:D19]) = 13 Then
  29.                          Sh.Copy , Sh
  30.                          Set Sh = ActiveSheet
  31.                         Sh.[D7:J19] = ""
  32.                     End If
  33.                 End If
  34.             Next
  35.         i = i + 1
  36.         Loop
  37.         .AutoFilterMode = False       '自動篩選模式:取消
  38.         .UsedRange.Offset(1).Clear    '資料輸入後清除掉
  39.        ' .Cells(1, .Columns.Count).EntireColumn = ""
  40.     End With
  41. End Sub
  42. Function 類別表(類別 As String)    '自訂函數: 尋找類別的工作表
  43.     Dim 表 As String, Sh As Worksheet
  44.     For Each Sh In Sheets                  'Sheets: 工作表的集合
  45.         If InStr(Sh.Name, 類別) = 1 And Application.CountA(Sh.[D7:D19]) = 13 Then  '類別的工作表[D7:D19]有輸入的資料數
  46.             表 = Sh.Name
  47.         ElseIf InStr(Sh.Name, 類別) = 1 And Application.CountA(Sh.[D7:D19]) < 13 Then
  48.             類別表 = Sh.Name
  49.             Exit For
  50.         End If
  51.     Next
  52.     If 類別表 = "" And 表 <> "" Then
  53.         Sheets(表).Copy , Sheets(表)
  54.         類別表 = ActiveSheet.Name
  55.     ElseIf 類別表 = "" And 表 = "" Then
  56.         '*** 找不到類別的工作表 複製 "表格" 的範本
  57.         Sheets("表格").Copy Sheets(1)
  58.         ActiveSheet.Name = 類別
  59.         類別表 = 類別
  60.     End If
  61. End Function
複製代碼
回復 23# yen956
沒有關係的,論壇需要熱心的會員參與.
作者: iceandy6150    時間: 2014-2-5 17:34

感謝G大及Y大的回復

我想再問一兩個小問題

1.每次寫程式,我都知道我想要做到什麼功能,但是程式都寫不出來,或錯
   要買什麼書來看才能增進我的程式能力呢?
   錄製巨集只能錄到操作過程,但是人為判斷及選擇,巨集錄不到

2.我現在設了一個參照表
            A           B
   1    物品    物品271
   2    保險    保險236
   3    一般    一般218

也將G大教的部分功能修改,我想讓程式從SHEET1(輸入區)去找類別
然後會去<參照表>尋找,例如找到(保險)(A,2),那就將(B,2)的值傳給K
但是不知道如何做到,再麻煩各位熱心版友
謝謝
  1. Private Sub CommandButton4_Click()
  2.             
  3. Dim i As Integer, j, k As String


  4.     With Sheets("Sheet1")
  5.    
  6.     .UsedRange.Range("G:G").AdvancedFilter xlFilterCopy, , .Cells(1, .Columns.Count), True
  7.     End With
  8.    
  9. i = 2
  10.             With Sheets("參照表")
  11.             Set Rng = .Range("A:A").Find(what:=Sheets("Sheet1").Cells(i, .Columns.Count))
  12.            k =.Range("A:A").Find(what:=Sheets("Sheet1").Cells(i, .Columns.Count).Next.Value)

  13. '我要將所找到的儲存格右邊那格的值傳給K,可是語法不對,我也不會
  14.            
  15.             MsgBox (Rng)
  16.             MsgBox (k)
  17.             
  18.             End With
  19. End Sub
複製代碼

作者: GBKEE    時間: 2014-2-5 17:52

回復 25# iceandy6150
多錄製巨集:可知如何使用VBA的方法.函數.屬性時機,要功力的增進,不二方法下苦工(多看,多問,多練習).大多數書籍的內容,VBA說明都可找到.
  1. Option Explicit
  2. Private Sub CommandButton4_Click()
  3.     Dim i As Integer, j, k As String, Rng As Range
  4.     With Sheets("Sheet1")
  5.         .UsedRange.Range("G:G").AdvancedFilter xlFilterCopy, , .Cells(1, .Columns.Count), True
  6.     End With
  7.     i = 2
  8.     With Sheets("參照表")
  9.         Set Rng = .Range("A:A").Find(what:=Sheets("Sheet1").Cells(i, .Columns.Count))
  10.         k = Rng.Offset(, 1)
  11.         MsgBox (Rng)
  12.         MsgBox (k)
  13.     End With
  14. End Sub
複製代碼

作者: iceandy6150    時間: 2014-2-5 20:46

回復 26# GBKEE


    天啊,就這麼一行
 k = Rng.Offset(, 1)
G大,很感謝你
我下午試了一個多小時,就試不出來
activecell.next.value不行
selection.next.value不行
先selection.select再activecell.next.value也不行
selection.address可以秀出Rng找到哪一個
但是傳回來的是$A$5的東西
我想要右移一格$B$5的值卻不會寫
有address要去找該位置的值,我也不會
我都快瘋了我

G大,像我這種問題,靠錄製巨集能有解答?
我買了一本VBA的書,有300項以上的語法,還是查不到
唉…超菜的我
作者: iceandy6150    時間: 2014-2-6 00:39

  1. Private Sub CommandButton3_Click()
  2.     Dim Sh As Worksheet, i As Integer, ii As Integer, R As Integer, Ar 'Dim 宣告變數
  3.     Dim k As Integer
  4.     Dim j As String
  5.     Dim A As Range, Rng As Range, xRow As Range
  6.    
  7.     Application.DisplayAlerts = False
  8.     Application.ScreenUpdating = False
  9.     For Each Sh In Sheets
  10.    
  11.         If Sh.Name <> "Sheet1" And Sh.Name <> "總表" And Sh.Name <> "表格範本" And Sh.Name <> "黏存單(零)" And Sh.Name <> "參照表" Then Sh.Delete
  12.         '活頁簿只留 工作表1:是輸入區,工作表2:是歷史記錄 ,"表格範本",黏存單(零),參照表
  13.     Next
  14.    
  15.     With Sheets("總表")
  16.         If .UsedRange.Rows.Count = 1 Then              '沒有歷史紀錄
  17.            Sheets("Sheet1").UsedRange.Copy            '複製(含標頭)
  18.             .Range("A1").PasteSpecial xlPasteValues
  19.             
  20.         Else
  21.             Sheets("Sheet1").UsedRange.Offset(1).Copy  '複製(不含標頭)
  22.             Sheets("總表").Range("A" & .UsedRange.Rows.Count).Offset(3).PasteSpecial xlPasteValues
  23.             'Offset(3) :空2列->第3列貼上
  24.            
  25.         End If
  26.         
  27.     End With
  28.    
  29.    
  30.     With Sheets("Sheet1")
  31.    
  32.     .UsedRange.Range("G:G").AdvancedFilter xlFilterCopy, , .Cells(1, .Columns.Count), True
  33.     '進階篩選 E欄 不重複資料到工作表最右欄 ***取得類別的分類***
  34.     'AdvancedFilter:進階篩選
  35.     'xlFilterCopy:進階篩選的資料顯示在其他地方
  36.     '.Cells(1, .Columns.Count) ->工作表的最右欄第1個儲存格->進階篩選的資料顯示的地方
  37.        i = 2
  38.         Do While .Cells(i, .Columns.Count) <> ""                  '工作表最右欄的儲存格 <>""
  39.             .Range("A:G").AutoFilter 7, .Cells(i, .Columns.Count)          'AutoFilter: 自動篩選 ,第7欄(類別)的準則為 .Cells(i, .Columns.Count)
  40.             Sheets("表格範本").Copy , Sheets(Sheets.Count)
  41.             Set Sh = ActiveSheet
  42.             
  43.             
  44.             With Sheets("參照表")
  45.             Set Rng = .Range("A:A").Find(what:=Sheets("Sheet1").Cells(i, .Columns.Count))
  46.             'MsgBox (Rng)
  47.             j = Rng.Offset(, 1)
  48.             End With
  49.             
  50. '@@@上面那行  j = Rng.Offset(, 1)     有時候跑一次能執行,後來就警告了      

  51.             Sh.[C2] = j      '@@@有時候是警告這一行錯誤
  52.             Sh.Name = Rng
  53.             
  54.             j = ""              '這兩行是我覺得使用後清空,加這兩行錯誤也沒消失
  55.             Rng = ""
  56.             

  57.             For Each xRow In .AutoFilter.Range.SpecialCells(xlCellTypeVisible).Rows '自動篩選範圍列的集合

  58.                 If xRow.Row > 1 Then

  59.                      R = Application.CountA(Sh.[D7:D19])                 '有輸入的資料數

  60.                      With Sh.[D7].Offset(R)

  61.                         .Cells(, 1) = xRow.Range("D1")

  62.                         .Cells(, 5) = xRow.Range("F1")

  63.                         .Cells(, 7) = xRow.Range("E1")

  64. '@@@  大大,這邊可能還要再把日期加進E3,我不會寫 (其實看不太懂為什麼,所以不會改)
  65.                      End With

  66.                      If Application.CountA(Sh.[D7:D19]) = 13 Then

  67.                          Sh.Copy , Sh

  68.                          Set Sh = ActiveSheet

  69.                         Sh.[D7:J19] = ""

  70.                     End If

  71.                 End If

  72.             Next
  73.             i = i + 1
  74.        Loop
  75.         
  76.         k = 1
  77.         Do While .Cells(k, .Columns.Count) <> ""
  78.         .Cells(k, .Columns.Count) = ""
  79.         k = k + 1
  80.         Loop
  81.         
  82.         '.Cells(1, .Columns.Count).CurrentRegion = ""
  83.         .AutoFilterMode = False
  84.     End With
  85.     Application.ScreenUpdating = True
  86.     Me.Activate

  87. End Sub
複製代碼
回復 26# GBKEE

大大,我把您第一次的程式修改一下,可是有些地方警告說沒有WITH和區域變數
快完成了,幫我看看,謝謝

[attach]17426[/attach]

[attach]17427[/attach]

庶字第XX號,的XX由人工手動輸入即可

[attach]17428[/attach]
作者: iceandy6150    時間: 2014-2-6 01:10

版大,不好意思,不知道為什麼會重覆傳,還有檔案、圖片都上不去,有空再傳一次,重覆的文再請版大刪掉,謝謝
作者: c_c_lai    時間: 2014-2-6 06:16

回復 30# iceandy6150
如果你目前使用的的網頁軟體無法上傳檔案的話,
請改用別的網頁軟體來上傳。
譬如你原本是使用 Firefox 上傳檔案,如果無法上傳,
則請試試改用 IE 來上傳檔案。
作者: iceandy6150    時間: 2014-2-6 07:14

回復 34# c_c_lai

C大您好,不知道為什麼,第3頁以後的文章,包括您的文章,都無法顯示了
我只能從[提醒]裡面去按回覆您的文章

昨晚我用IE開兩三個視窗無效,用CHROME開兩三個也無效
自己回覆的帖也看不到,只能看到第30則文章而已

[attach]17434[/attach]
作者: c_c_lai    時間: 2014-2-6 07:54

回復 31# iceandy6150
你可以請教  小誌版大。
作者: GBKEE    時間: 2014-2-6 07:57

回復 28# iceandy6150
錄製巨集能有解答?? 還要多看VBA說明.練習,了解它的範例(書本上的函數,方法,屬性,VBA說明都有)

[attach]17435[/attach]
  1. With Sheets("參照表")
  2.             Set Rng = .Range("A:A").Find(what:=Sheets("Sheet1").Cells(i, .Columns.Count))
  3.             MsgBox Rng Is Nothing '是 True 沒有找到 下面就錯誤
  4.             '沒有物件指定到 Rng
  5.             j = Rng.Offset(, 1)
  6.             End With
  7.             Sh.[C2] = j      'Rng Is Nothing 也會有錯誤
  8.             Sh.Name = Rng    'Rng Is Nothing 也會有錯誤
  9.             
  10.             j = ""              '沒用的:這兩行是我覺得使用後清空,加這兩行錯誤也沒消失
  11.             Rng = ""
  12.             For Each xRow In .AutoFilter.Range.SpecialCells(xlCellTypeVisible).Rows '自動篩選範圍列的集合
  13.                 If xRow.Row > 1 Then
  14.                      R = Application.CountA(Sh.[D7:D19])                 '有輸入的資料數
  15.                      With Sh
  16.                         .[E3] = xRow.Range("B1")                        '@@@  再把日期加進E3
  17.                         .[D7].Offset(R).Cells(, 1) = xRow.Range("D1")
  18.                         .[D7].Offset(R).Cells(, 5) = xRow.Range("F1")
  19.                         .[D7].Offset(R).Cells(, 7) = xRow.Range("E1")
  20.                      End With
複製代碼

作者: iceandy6150    時間: 2014-2-6 21:43

回復 33# GBKEE

我終於完成囉,附上檔案

[attach]17445[/attach]

感謝G大及其他熱心版友的幫忙
作者: c_c_lai    時間: 2014-2-7 06:17

回復 34# iceandy6150
請將以下之七項 "X: X" 內之空白去除;
  1. 1.  .UsedRange.Range("G: G").AdvancedFilter xlFilterCopy, , .Cells(1, .Columns.Count), True
  2. 2.  .Range("A: G").AutoFilter 7, .Cells(i, .Columns.Count)  '  AutoFilter:  自動篩選 ,第7欄(類別)的準則為 .Cells(i, .Columns.Count)
  3. 3.  Set Rng = .Range("A1: A18").Find(What:=M)
  4. 4.  R = Application.CountA(Sh.[D7: D19])   '  有輸入的資料數
  5. 5.  If Application.CountA(Sh.[D7: D19]) = 13 Then
  6. 6.  Sh.[D7: J19] = ""
  7. 7.  Sh.[D33: J45] = ""
複製代碼
否則會產生錯誤訊息。 (正確應為 "X:X")
  1. 1.  .UsedRange.Range("G:G").AdvancedFilter xlFilterCopy, , .Cells(1, .Columns.Count), True
  2. 2.  .Range("A:G").AutoFilter 7, .Cells(i, .Columns.Count)  '  AutoFilter:  自動篩選 ,第7欄(類別)的準則為 .Cells(i, .Columns.Count)
  3. 3.  Set Rng = .Range("A1:A18").Find(What:=M)
  4. 4.  R = Application.CountA(Sh.[D7:D19])   '  有輸入的資料數
  5. 5.  If Application.CountA(Sh.[D7:D19]) = 13 Then
  6. 6.  Sh.[D7:J19] = ""
  7. 7.  Sh.[D33:J45] = ""
複製代碼

作者: c_c_lai    時間: 2014-2-7 06:28

回復 34# iceandy6150
又、以下處裡清除動作:
  1.         '  k = 1
  2.         '  Do While .Cells(k, .Columns.Count) <> ""
  3.         '      .Cells(k, .Columns.Count) = ""
  4.         '      k = k + 1
  5.         '  Loop
複製代碼
可參考 GBKEE 在 "對特定欄進行篩選和替代資料" 一文中提及的簡潔、扼要之使用語法,
而替換 Do While ~ Loop 循環判斷直至條件不成立為止的用法
(P.S.  雖然此處只有兩欄資料,但總共卻執行了三趟)。
  1. .Cells(1, .Columns.Count).CurrentRegion = ""
複製代碼

作者: GBKEE    時間: 2014-2-7 09:16

本帖最後由 GBKEE 於 2014-2-7 09:21 編輯

回復 34# iceandy6150
萬丈高樓,從地起,你已在打地基了
依你的 [零用金清單-上傳用.rar] 修改一下
  1. Option Explicit   '必須置於模組頂端 強制宣告變數
  2. Private Sub CommandButton1_Click()
  3.     Dim Sh As Worksheet, i As Integer, R As Integer, Rng As Range, xRow As Range
  4.     Application.ScreenUpdating = False
  5.     With Sheets("總表")
  6.         If .UsedRange.Rows.Count = 1 Then              '沒有歷史紀錄
  7.            Sheets("Sheet1").UsedRange.Copy             '複製(含標頭)
  8.             .Range("A1").PasteSpecial xlPasteValues
  9.         Else
  10.             Sheets("Sheet1").UsedRange.Offset(1).Copy  '複製(不含標頭)
  11.             .Range("A" & .UsedRange.Rows.Count).Offset(3).PasteSpecial xlPasteValues
  12.                                                        'Offset(3) :空2列->第3列貼上
  13.         End If
  14.     End With
  15.     With Sheets("Sheet1")
  16.         .UsedRange.Range("G:G").AdvancedFilter xlFilterCopy, , .Cells(1, .Columns.Count), True
  17.         i = 2
  18.         Do While .Cells(i, .Columns.Count) <> ""                          '工作表最右欄的儲存格 <>""
  19.             .Range("A:G").AutoFilter 7, .Cells(i, .Columns.Count)          'AutoFilter: 自動篩選 ,第7欄(類別)的準則為 .Cells(i, .Columns.Count)
  20.             Set Rng = Sheets("參照表").Range("A1:A18").Find(.Cells(i, .Columns.Count)).Offset(, 1)
  21.             Set Sh = Sheets(類別表(Rng))
  22.             Sh.Activate
  23.             For Each xRow In .AutoFilter.Range.SpecialCells(xlCellTypeVisible).Rows '自動篩選範圍列的集合
  24.                 If xRow.Row > 1 Then
  25.                     R = Application.CountA(Sh.[D7:D19])                 '有輸入的資料數
  26.                     With Sh
  27.                         .[E3,E29] = xRow.Range("B1")                    '日期加進E3,E29
  28.                         
  29.                         .[D7].Offset(R).Cells(, 1) = xRow.Range("D1")
  30.                         .[D7].Offset(R).Cells(, 5) = xRow.Range("F1")
  31.                         .[D7].Offset(R).Cells(, 7) = xRow.Range("E1")
  32.                         
  33.                         .[D33].Offset(R).Cells(, 1) = xRow.Range("D1")
  34.                         .[D33].Offset(R).Cells(, 5) = xRow.Range("F1")
  35.                         .[D33].Offset(R).Cells(, 7) = xRow.Range("E1")
  36.                     End With
  37.                     If Application.CountA(Sh.[D7:D19]) = 13 Then
  38.                         Sh.Copy , Sh
  39.                         Set Sh = ActiveSheet
  40.                         Sh.[D7:J19,D33:J45] = ""
  41.                         'Sh.[D33:J45] = ""
  42.                     End If
  43.                 End If
  44.             Next
  45.             i = i + 1
  46.         Loop
  47.         .AutoFilterMode = False   '**** 取消自動篩選模式,資料全部顯示下面的清除才有效果*****
  48.    '     .UsedRange.Offset(1) = "'"                      'UsedRange: 工作表的已使用範圍
  49.         '.Cells(1, .Columns.Count).EntireColumn = ""    'EntireColumn:整欄
  50.         '.Cells(1, .Columns.Count).CurrentRegion = ""   'CurrentRegion: 有資料的延伸範圍
  51.      '   .Activate
  52.     End With
  53.     Application.ScreenUpdating = True
  54. End Sub
  55. Function 類別表(類別 As Range) As String      '自訂函數: 尋找類別的工作表
  56.     Dim 表 As String, Sh As Worksheet
  57.     For Each Sh In Sheets                  'Sheets: 工作表的集合
  58.         If InStr(Sh.Name, 類別) = 1 And Application.CountA(Sh.[D7:D19]) = 13 Then  '類別的工作表[D7:D19]有輸入的資料數
  59.             表 = Sh.Name
  60.         ElseIf InStr(Sh.Name, 類別) = 1 And Application.CountA(Sh.[D7:D19]) < 13 Then
  61.             類別表 = Sh.Name
  62.             Exit For
  63.         End If
  64.     Next
  65.     If 類別表 = "" And 表 <> "" Then
  66.         Sheets(表).Copy , Sheets(表)
  67.         ActiveSheet.[C2] = 類別.Offset(, 2)
  68.         類別表 = ActiveSheet.Name
  69.     ElseIf 類別表 = "" And 表 = "" Then
  70.         '*** 找不到類別的工作表 複製 "表格" 的範本
  71.         Sheets("表格範本").Copy Sheets(1)
  72.         ActiveSheet.Name = 類別
  73.         ActiveSheet.[C2] = 類別.Offset(, 1)
  74.         類別表 = 類別
  75.     End If
  76. End Function
複製代碼

作者: Hsieh    時間: 2014-2-7 14:14

回復 34# iceandy6150
湊個熱鬧
  1. Sub CreateTable()
  2. Dim i%, Ar(), Rng As Range, A As Range, sht As Object, ky As Variant, k&, s&
  3. Set sht = CreateObject("Scripting.Dictionary")
  4. Application.DisplayAlerts = False
  5. With Sheets("Sheet1")
  6. i = .Index + 1
  7. Do Until Sheets.Count < i '刪除Sheet1之後的工作表
  8.    Sheets(i).Delete
  9.    i = .Index + 1
  10. Loop
  11. For Each A In .Range(.[G2], .[G2].End(xlDown)) '分類儲存
  12.   Set Rng = Sheets("參照表").[A:A].Find(A, lookat:=xlWhole) '找到參照
  13.   If IsEmpty(sht(Rng.Offset(, 1).Value)) Then '分類第一個
  14.   ReDim Preserve Ar(0)
  15.      Ar(0) = Array(A.Offset(, -3).Value, "", "", "", A.Offset(, -1).Value, "", A.Offset(, -2).Value)
  16.      sht(Rng.Offset(, 1).Value) = Ar
  17.      Else '分類繼續找到
  18.      Ar = sht(Rng.Offset(, 1).Value)
  19.      s = UBound(Ar)
  20.      ReDim Preserve Ar(s + 1)
  21.      Ar(s + 1) = Array(A.Offset(, -3).Value, "", "", "", A.Offset(, -1).Value, "", A.Offset(, -2).Value)
  22.      sht(Rng.Offset(, 1).Value) = Ar
  23.      Erase Ar
  24.    End If
  25. Next
  26. For Each ky In sht.keys '用分類當成索引值
  27. Ar = sht(ky)
  28. s = UBound(Ar) + 1
  29. With Sheets.Add(after:=Sheets(Sheets.Count)) '新增工作表
  30. .Name = ky '以分類為表名稱
  31.   Set Rng = Sheets("表格範本").[A1:K22] '表格範本範圍
  32.   Rng.Copy .[A1]: k = 0: .Cells(k + 2, 3) = ky
  33.   For i = 0 To UBound(Ar) '寫入資料
  34.      .Cells(i + 7 + Int(i / 13) * 13, 4).Resize(, 7) = Application.Index(Ar, i)
  35.     If (i + 1) Mod 13 = 0 Then k = k + 26: Rng.Copy .[A1].Offset(k, 0): .Cells(k + 2, 3) = ky '13筆為一個表格
  36.   Next
  37. End With
  38. Next
  39. '轉至總表
  40. If MsgBox("是否存入總表", vbYesNo) = 6 Then .Range("A1").CurrentRegion.Offset(1).Copy Sheets("總表").Cells(.Rows.Count, 1).End(xlUp).Offset(3)
  41. MsgBox "分類完成"
  42. End With
  43. End Sub
複製代碼

作者: iceandy6150    時間: 2014-2-7 23:00

本帖最後由 iceandy6150 於 2014-2-7 23:06 編輯

回復 38# Hsieh

感謝很多大大熱心回復,感動到快哭了
來不及消化之前,先發問一下

我原本的程式裡面加了防呆功能,Sheet1最右邊篩選出來的,如果參照表沒有該類別,會出錯
於是加了下列程式
            With Sheets("參照表")
            M = Sheets("Sheet1").Cells(i, .Columns.Count).Value
            Set Rng = .Range("A2:A30").Find(What:=M)
            
            If Rng Is Nothing Then
                MsgBox ("找不到<<" & M & ">>相對應類別,請增修參照表")
                MsgBox ("請記得去總表把本次資料刪除,以免重覆")
                Sheets("Sheet1").AutoFilterMode = False
                Application.ScreenUpdating = True
                Me.Activate
                Exit Sub
            End If

           Sh.[C2] = Rng.Offset(, 2)
            Sh.Name = Rng.Offset(, 1)
            End With

然後Sheet1的[類別]欄為了怕輸入參照表沒有的東西,所以設了下拉式選單
還有為了清除乾淨,讓第二次、第三次使用時,.usedrange.rows.count不會出錯
(明明下面列都沒東西了,還是抓很下面的列)
所以用程式去做輕除,設了按鈕2,如下

Private Sub CommandButton2_Click()
     Worksheets("參照表").Activate
     Worksheets("參照表").Range("A1:A30").Select
     Worksheets("參照表").Range("A30").Activate
     Selection.CreateNames Top:=True, Left:=False, Bottom:=False, Right:= _
     False
'其實A1:A30應該是A1到A欄有資料的最後那一列,但我不會設
'只好先預設30個類別,以上是錄製巨集再複製貼上的

     Worksheets("Sheet1").Activate
Sheets("Sheet1").Range("A2:G150").Delete (xlShiftUp)
'這兩行是清空資料,一樣是預設到150,絕對夠用
'如果要~有多少資料就刪除多少資料,我又不會了

With Sheets("Sheet1")
    With .Range("G2:G150").Validation
        .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
         xlBetween, Formula1:="=類別"
        .IgnoreBlank = True
        .InCellDropdown = True
        .InputTitle = ""
        .ErrorTitle = ""
        .InputMessage = ""
        .ErrorMessage = ""
        .IMEMode = xlIMEModeNoControl
        .ShowInput = True
        .ShowError = True
    End With
End With
End Sub
'這邊是設定下拉式選單,一樣錄巨集再貼過來用

最後想設一個防呆,檢查Sheet1的G欄(類別),是否有[空白]
如果沒輸入,就不能篩選分類,也沒辦法去<參照頁>對照
大概知道要設定範圍~~Sheet1.Range(G2到G欄最後一列)
如果此範圍有空白欄,警告,並Exit sub
但我試不出來,請教各位大大解答了   <按鈕4>

Private Sub CommandButton4_Click()
Dim i
'方法一,失敗
For Each c In Sheets("Sheet1").UsedRange("G:G")
If c = "" Then i = 1
Else i = 0
End If
Next
'方法二,失敗
'If IsEmpty(Sheets("Sheet1").UsedRange("G:G")) Then
'方法三,失敗
'If Sheets("Sheet1").UsedRange("G:G").SpecialCells(xlCellTypeBlanks) Is Nothing Then
'方法四,失敗
'i = Sheets("Sheet1").UsedRange("G:G").SpecialCells(xlCellTypeBlanks)
'MsgBox (i)

If i = 1 Then MsgBox ("有空格")
Else
MsgBox ("無空格")
End If
End Sub

其實好像應該先檢查Sheet1.usedrange.rows.count
(先知道輸入幾筆資料,假設23筆)
再去數G欄有幾筆,小於23筆就知道有某幾筆沒填類別
有時候1~18筆都有選類別,19.20.21沒選,22.23有選

以上發問,感謝
作者: GBKEE    時間: 2014-2-8 09:51

回復 39# iceandy6150
  1. Option Explicit
  2. Private Sub CommandButton2_Click()
  3.     Sheets("參照表").UsedRange.Columns(1).CreateNames True
  4.     With Sheets("Sheet1").Range("G2:G150").Validation
  5.         .Add Type:=xlValidateList, Formula1:="=" & Sheets("參照表").UsedRange.Cells(1)
  6.     End With
  7. End Sub
  8. Private Sub CommandButton4_Click()
  9.     Dim i As Integer, C As Range
  10.     For Each C In Sheets("Sheet1").UsedRange.Columns(7).Cells
  11.         If C = "" Then MsgBox ("有空格"): Exit Sub
  12.     Next
  13.     MsgBox ("無空格")
  14. End Sub
  15. Sub Ex()
  16.     Dim i As Integer
  17.     'UsedRange.RANGE("G:G") -> 已使用範圍的G欄會延伸到工作表的的底部
  18.     'UsedRange.Columns(7)   -> 僅已使用範圍第1欄範圍算起的第7欄範圍
  19.     For i = 1 To 3
  20.         With Sheets.Add(, Sheets(Sheets.Count))
  21.             If i = 1 Then
  22.                 .[F1,I5] = "AA"
  23.             ElseIf i = 2 Then
  24.                 .[D1,F5] = "AA"
  25.             Else
  26.                 .[D2,F5] = "AA"
  27.             End If
  28.             MsgBox .UsedRange.Address
  29.             MsgBox .UsedRange.Columns(5).Address
  30.             MsgBox .UsedRange.Range("E:E").Address        '.[D2,F5]->工作表第一列沒資料有錯誤
  31.         End With
  32.     Next
  33. End Sub
複製代碼

作者: iceandy6150    時間: 2014-2-10 09:51

回復 40# GBKEE


    G大,有錯誤產生

01.Option Explicit

02.Private Sub CommandButton2_Click()

03.    Sheets("參照表").UsedRange.Columns(1).CreateNames True

04.    With Sheets("Sheet1").Range("G2:G150").Validation

05.        .Add Type:=xlValidateList, Formula1:="=" & Sheets("參照表").UsedRange.Cells(1)

06.    End With

07.End Sub


第05行,錯誤1004,應用程式或物件定義上的錯誤
不曉得為什麼會這樣
謝謝
作者: GBKEE    時間: 2014-2-10 10:08

回復 41# iceandy6150
  1. Private Sub CommandButton2_Click()
  2.     Sheets("參照表").UsedRange.Columns(1).CreateNames True
  3.     With Sheets("Sheet1").Range("G2:G150").Validation
  4.         .Delete  '加上這行 如還有錯誤,請上傳檔案
  5.       '.Delete  2003版可不用.
  6.         .Add Type:=xlValidateList, Formula1:="=" & Sheets("參照表").UsedRange.Cells(1)
  7.     End With
  8. End Sub
複製代碼

作者: iceandy6150    時間: 2014-2-10 12:45

回復 42# GBKEE


    G大可以了耶
這也太神奇了,為什麼會這樣呢? 可以指導說明一下嗎?謝謝
作者: GBKEE    時間: 2014-2-10 12:59

回復 43# iceandy6150
OFFICE的版本不同
作者: iceandy6150    時間: 2014-2-10 22:41

回復 44# GBKEE

我可不可以在請問一下  UsedRange的用法

我發現如果一個工作表的A1~A10有畫框線 (或稱為表格也行)

然後只有A1~A5填入資料,A6~A10是空格

這樣情況下  使用with sheets("工作表")

.UsedRange.Rows.count會算到10,而不是5

若針對.UsedRange這個範圍去使用CountA會數出5個

但如果我不想計算框線,也不是要算這個範圍中有數值的是幾個
只想找到有填入數值的最後一個格子
而且中間可能會有空格,該怎麼辦呢?

如下圖,我想找G欄的最後一筆資料,目前是G55
可是每個月增加資料後,可能會變G58、G63等等的

[attach]17465[/attach]
作者: GBKEE    時間: 2014-2-11 09:42

回復 45# iceandy6150
  1. End 屬性 該物件代表包含來源範圍之區域結尾處的儲存格。等於按 END+向上鍵、END+向下鍵、END+向左鍵或 END+向右鍵。唯讀 Range 物件。
  2. expression.End (Direction)
  3. Direction    必選的 XlDirection 資料類型。要移往的方向。
  4. XlDirection 可以是這些 XlDirection 常數之一。
  5. xlDown
  6. xlToRight
  7. xlToLeft
  8. xlUp
複製代碼
  1. Sub Ex()
  2.     With ActiveSheet.Range("G:G")
  3.        MsgBox .Cells(.Count).End(xlUp).Address
  4.     End With
  5.     With ActiveSheet
  6.        MsgBox .Range("G" & .Rows.Count).End(xlUp).Address
  7.     End With
  8.     With ActiveSheet
  9.        MsgBox .Cells(.Rows.Count, "G").End(xlUp).Address
  10.     End With
  11.     With ActiveSheet
  12.        MsgBox .Cells(.Rows.Count, 7).End(xlUp).Address
  13.     End With
  14. End Sub
複製代碼

作者: iceandy6150    時間: 2014-2-11 23:52

本帖最後由 iceandy6150 於 2014-2-11 23:54 編輯

回復 46# GBKEE

大大,您寫得程式正常運作無誤,感謝
只是我有點好奇   .Range("G" & .Rows.Count).End(xlUp).Address
我是改成.Range("G" & .Rows.Count).End(xlUp).Value
因為我需要那一格的值
好奇的地方是為什麼您用 xlup ?
我們不是要找某範圍最下面一格儲存格,應該是xldown?

另外想在請問一個頭痛的問題
如下圖
是一個類似會計計帳的EXCEL表格
很令人傻眼的是,月份中間居然會有空白處 (資料不連續)
然後日期也只有打月、日
真正會用到的數字是在紅色格線的上面
以人眼看,是還算清楚,但是要用程式抓資料,很頭大捏
因為不是每一排都有年月日可以參考

[attach]17476[/attach]

還有更傻眼的如下圖

[attach]17477[/attach]

把EXCEL當作簿子使用,連頁數都有,但是102年只有一格
下面的就通通代表102年發生的了
然後不是每個月都有資料,本圖只有1、6、12月才有資料
而且本圖是要抓F欄位,紅色格線上方828,170那個數據


所需功能概述:
假設有A,B,C,D,E五種會計科目,分別是五張工作表
另外每個月結算需要一個結算工作表
需要到A,B,C,D,E去抓資料,到<結算>工作表,再去加加減減

那A,B,C工作表可能是像圖1,每個月一定有資料,但會有空格
我只要找G欄最下方一個數值,貼過去<結算>,就完成了
(這邊也使用G大教學,已可執行)

但D,E工作表可能是像圖2
資料不是每個月都有
比如我要結103年02月的資料
ABC是沒問題
DE如果有103年02月的資料才抓到<結算>
如果如圖2,沒有資料則不抓

要是我使用.Range("F" & .Rows.Count).End(xlUp).Value
勢必會抓錯,把102年12月31日的828170這筆資料誤貼過去<結算>
而那種怪異的年月日格式,如何讓程式不會誤判呢?

謝謝
作者: GBKEE    時間: 2014-2-12 07:19

回復 47# iceandy6150
.Rows.Count : 傳回物件列的總數
.Range("G" & .Rows.Count) : 這儲存格是位於G欄最底部的列號
為什麼是 xlup ? (往上),不是 應該是xldown(往下)
Range("G" & .Rows.Count).End(xldown).Value  :還是最底部列的儲存格

請將檔案的範例上傳看看
作者: iceandy6150    時間: 2014-2-12 17:11

回復 48# GBKEE

大大,感謝解說

檔案我刪掉一些東西後,上傳
裡面最右邊是<損益表>
藍色範圍是要去找的相關類別工作表
我有設一個按鈕,寫了部分的程式
橘色是要填入資料的地方

其餘沒顏色的部分就暫不處理
事後我再修就好

[attach]17482[/attach]

我想是不是要設一個輸入區
詢問使用者想產生哪一個月的損益表
例如103年01月

那程式就去各類工作表,如果有103年01月的資料
就放到<損益表>相關欄位去
如果沒有,就不放

只是各類工作表真的長得很怪....

[attach]17483[/attach]
作者: GBKEE    時間: 2014-2-13 10:08

回復 49# iceandy6150
  1. '費用項目中 "津  貼",有空格,工作表名稱"津貼59-60"中沒空格
  2. '所有費用項目需與工作表名稱(費用項目??_??)一致
  3. '否則 Sh = Filter(Ar, Trim(Rng(1).Cells(i)), True) 會不正確'
  4. Option Explicit
  5. Sub Ex()
  6.     Dim xlMon As Integer, xlYear As String, E As Variant
  7.     Dim Rng(1 To 2) As Range, Rng_Ar(), Ar(), i As Integer, Sh As Variant
  8.     With Sheets("損益表")
  9.         xlYear = Mid(.[a3], InStrRev(.[a3], "至") + 1, InStrRev(.[a3], "年") - InStrRev(.[a3], "至"))
  10.         'xlYear : 損益表的年度
  11.         xlMon = Mid(.[a3], InStrRev(.[a3], "年") + 1, InStrRev(.[a3], "月") - InStrRev(.[a3], "年") - 1)
  12.         'xlMon : 損益表的月份
  13.         Set Rng(1) = .[A18:A30]                         '費用項目
  14.         ReDim Rng_Ar(1 To Rng(1).Count)                 '陣列:元素數 = 費用項目數
  15.     End With
  16.     ReDim Ar(1 To Sheets.Count)                         '陣列:元素數 = Sheets.Count
  17.     For i = 1 To Sheets.Count
  18.         Ar(i) = Sheets(i).Name                          '陣列:元素導入 Sheets.Name
  19.     Next
  20.     For i = 1 To Rng(1).Count
  21.         Sh = Filter(Ar, Trim(Rng(1).Cells(i)), True)
  22.         'Filter 函數 傳回一個從零開始的陣列,該陣列包含基於指定篩選準則的一個字串陣列的子集。
  23.         For Each E In Sh
  24.             With Sheets(E)                              '有"費用項目"名稱的 工作表
  25.                 Set Rng(2) = .[A:B].Find(xlYear, lookat:=xlWhole, LookIn:=xlValues) '核對年度
  26.                 If Not Rng(2) Is Nothing Then
  27.                     Set Rng(2) = .[a:a].Find(xlMon, lookat:=xlWhole)                '搜尋月份
  28.                     If Not Rng(2) Is Nothing Then
  29.                         Rng_Ar(i) = Rng_Ar(i) + Rng(2).Range("F1")                  'Range("F1"):金額位置
  30.                     End If
  31.                 End If
  32.             End With
  33.         Next
  34.     Next
  35.     Rng(1).Offset(, 1) = Application.WorksheetFunction.Transpose(Rng_Ar)
  36.     'Transpose(轉置) : 一維陣列(橫式) 轉換為 二維陣列(這裡變一列直式)
  37. End Sub
複製代碼

作者: iceandy6150    時間: 2014-2-13 23:24

回復 50# GBKEE

感謝G大,太神了

這麼詭異的表格也能找到方法統計
還不是很懂程式原理
但是自己測試是能正常運作
明天找使用者問看看

再次感謝!
作者: tainanfriend    時間: 2014-2-14 12:41

真的太厲害了
我是有看過另外一種資料分類的程式
它是用Excel中篩選的功能
將資料篩選出來後
再分類

不過
這裡的比較厲害
作者: iceandy6150    時間: 2014-2-15 18:51

本帖最後由 iceandy6150 於 2014-2-15 18:56 編輯

回復 50# GBKEE


G大,不好意思,又來發問了

壹、請問您的程式中,
        Rng_Ar(i) = Rng_Ar(i) + Rng(2).Range("F1")                  'Range("F1"):金額位置
       是去抓取下圖中ABCD哪一個位置呢?

       [attach]17497[/attach]

       雖然四個位置的值都一樣,實際使用上要選C
       不過只有A,是有月日可以對照
       好奇問一下

貳、其他的部分也需要加進程式中,可是我不會改
        [attach]17499[/attach]
      
        右上方黃色的格子,是要填入 <銷貨收入47-48>的F欄的倒數第2個值,也就是圖1的C
        但我上次弄錯了,以為是最後一個格子
        所以原本程式如下:
        Dim j
        With Sheets("銷貨收入47-48").Range("F:F")

       'Sheets("損益表").Range("C6").Value = .Cells(.Count).End(xlUp).Value 這行無法直接動作,故放棄

       j = .Cells(.Count).End(xlUp).Value
       Sheets("損益表").Range("C6").Value = j
    End With

     那我改成
        j = .Cells(.Count - 1).End(xlUp).Value  失敗,還是抓最下一格
         j = .Cells(.Count).End(xlUp).Offset(-1).Value 失敗,J值是空的

     [問題一]該怎麼改成倒數第二格呢?
   
[問題二]如果要使用G大的程式去動作,怎麼加呢?
另外,有些範圍也想加

圖2的藍色部分
期初存貨 B8 = <存貨5-6>的F欄的倒數第二格的值(其實C=ABD)
進貨 B9 = <進貨51-52>的F欄的倒數第二格的值

*減:期末存貨 B11 = <存貨5-6>的F欄的最後一格 (圖1的位置E)
(這邊就真的可以用 .Cells(.Count).End(xlUp).Value)

圖2下面有橘色部分,B35、B36、B37
其他收入:目前沒建立工作表,因為很少用到,但為了程式順利運作,可增設一空工作表名為<其他收入>
利息收入 B36 = <利息收入93-94>的G欄倒數第二格(圖1位置D)
拥金收入B37 = <佣金收入95-96>的G欄倒數第二格(圖1位置D)

原本G大的程式是設定A18~A30,實際可能是到A32,我可微調
(因為要上傳,有些東西我先刪掉)
但多了B8.B9.B11這三個不連續的,而且B11找的地方不一樣
B35、B36、B37,也是
如何讓這幾個也能判斷年月日,正常運作放資料,我就不會改了
作者: GBKEE    時間: 2014-2-16 08:23

回復 53# iceandy6150
[問題二] 待你附檔
[問題一] 如下
  1. For i = 1 To Rng(1).Count
  2.         Sh = Filter(Ar, Trim(Rng(1).Cells(i)), True)
  3.         'Filter 函數 傳回一個從零開始的陣列,該陣列包含基於指定篩選準則的一個字串陣列的子集。
  4.         For Each E In Sh
  5.             With Sheets(E)            '有"費用項目"名稱的 工作表
  6.                 Set Rng(2) = .[A:B].Find(xlYear, lookat:=xlWhole, LookIn:=xlValues, SearchOrder:=xlByRows) '核對年度
  7.                 If Not Rng(2) Is Nothing Then
  8.                     Set Rng(2) = .[a:a].Find(xlMon, lookat:=xlWhole)                '搜尋月份
  9.                     If Not Rng(2) Is Nothing Then Set Rng(2) = Rng(2).Resize(4, 100).Find("本月合計", lookat:=xlPart)              '搜尋本月合計
  10.                     'Rng(2).Resize(4,100):找到的月份位置.Resize(4,100):擴充範圍(4列,100欄)
  11.                     If Not Rng(2) Is Nothing Then
  12.                         Rng_Ar(i) = Rng_Ar(i) + Rng(2).Range("C1")                  'Range("C1")金額位置:本月合計的第3欄
  13.                     End If
  14.                 End If
  15.             End With
  16.         Next
  17.     Next
複製代碼

作者: iceandy6150    時間: 2014-2-16 11:28

本帖最後由 iceandy6150 於 2014-2-16 11:33 編輯

回復 54# GBKEE

感謝G大

再次上傳檔案,需求如#53篇所述

[attach]17506[/attach]

圖中紅色箭頭要取的值較為特殊,是該工作表最下面的總結

謝謝


附上檔案
[attach]17505[/attach]
作者: GBKEE    時間: 2014-2-17 07:41

回復 55# iceandy6150
銷貨收入:要合計哪些工作表的儲存格?
期初存貨:要合計哪些工作表的儲存格?
進    貨:要合計哪些工作表的儲存格?
  1. Option Explicit
  2. Sub Ex()
  3.     Dim xlMon As Integer, xlYear As String, A As Variant, E As Variant
  4.     Dim Rng(1 To 2) As Range, Rng_Ar(), Ar(), i As Integer, Sh As Variant
  5.     With Sheets("損益表")
  6.         xlYear = Mid(.[a3], InStrRev(.[a3], "至") + 1, InStrRev(.[a3], "年") - InStrRev(.[a3], "至"))
  7.         'xlYear : 損益表的年度
  8.         xlMon = Mid(.[a3], InStrRev(.[a3], "年") + 1, InStrRev(.[a3], "月") - InStrRev(.[a3], "年") - 1)
  9.         'xlMon : 損益表的月份

  10.         Set Rng(1) = .[A18:A32,A35:A37]                 '*****  支出,收入 ****
  11.         
  12.     End With
  13.     ReDim Ar(1 To Sheets.Count)                         '陣列:元素數 = Sheets.Count
  14.     For i = 1 To Sheets.Count
  15.         Ar(i) = Sheets(i).Name                          '陣列:元素導入 Sheets.Name
  16.     Next
  17.      For Each A In Rng(1).Areas                         '支出,收入不在連續的範圍
  18.                          'Areas 屬性 傳回 Areas 集合,此集合代表多重範圍中的所有範圍。唯讀。
  19.         ReDim Rng_Ar(1 To A.Count)                      '陣列:元素數 = 費用項目數
  20.         For i = 1 To A.Count
  21.             Sh = Filter(Ar, Trim(A.Cells(i)), True)
  22.             'Filter 函數 傳回一個從零開始的陣列,該陣列包含基於指定篩選準則的一個字串陣列的子集。
  23.             For Each E In Sh
  24.                 With Sheets(E)            '有"費用項目"名稱的 工作表
  25.                     Set Rng(2) = .[A:B].Find(xlYear, lookat:=xlWhole, LookIn:=xlValues, SearchOrder:=xlByRows) '核對年度
  26.                     If Not Rng(2) Is Nothing Then
  27.                         Set Rng(2) = .[a:a].Find(xlMon, lookat:=xlWhole)                '搜尋月份
  28.                         If Not Rng(2) Is Nothing Then Set Rng(2) = Rng(2).Resize(4, 100).Find("本月合計", lookat:=xlPart)              '搜尋本月合計
  29.                         'Rng(2).Resize(4,100):找到的月份位置.Resize(4,100):擴充範圍(4列,100欄)
  30.                         If Not Rng(2) Is Nothing Then
  31.                             If InStr(E, "收入") Then
  32.                                 Rng_Ar(i) = Rng_Ar(i) + Rng(2).Range("D1")          '貸  方 'Range("D1")金額位置:本月合計的第4欄
  33.                             Else
  34.                                 Rng_Ar(i) = Rng_Ar(i) + Rng(2).Range("C1")          '借  方 'Range("C1")金額位置:本月合計的第3欄
  35.                             End If
  36.                         End If
  37.                     End If
  38.                 End With
  39.             Next
  40.         Next
  41.         A.Offset(, 1) = Application.WorksheetFunction.Transpose(Rng_Ar)
  42.         'Transpose(轉置) : 一維陣列(橫式) 轉換為 二維陣列(這裡變一列直式)
  43.     Next
  44. End Sub
複製代碼

作者: iceandy6150    時間: 2014-2-17 19:05

本帖最後由 iceandy6150 於 2014-2-17 19:07 編輯

回復 56# GBKEE


    G大您真厲害,如果工作表是XX費用就是支出(借方),是找F欄
   如果XX收入就是(貸方),是找G欄。
  
    關於幾個不清楚的點

期初存貨: B8 = <存貨5-6>的F欄的倒數第二格的值                              

進貨: B9 = <進貨51-52>的F欄的倒數第二格的值

減:期末存貨: B11 = <存貨5-6>的F欄的"最後一格 "

銷貨收入:C6 = <銷貨收入>的F欄的倒數第二格的值

我把範圍改成 Set Rng(1) = .[A6,A8:A9,A11,A18:A32,A35:A37] 但是不太對  

有一個要放在C6卻放到B6,B8、B9放到B9、B10

再請大大幫我修一下

謝謝,感恩

[attach]17512[/attach]
作者: GBKEE    時間: 2014-2-18 15:25

回復 57# iceandy6150
  1. Option Explicit
  2. Sub Ex()
  3.     Dim xlMon As Integer, xlYear As String, A As Variant, E As Variant, Ay As String
  4.     Dim Rng(1 To 2) As Range, Rng_Ar(), Ar(), i As Integer, Sh As Variant, X As Integer
  5.     ReDim Ar(1 To Sheets.Count)                         '陣列:元素數 = Sheets.Count
  6.     For i = 1 To Sheets.Count
  7.         Ar(i) = Sheets(i).Name                          '陣列:元素導入 Sheets.Name
  8.     Next
  9.     With Sheets("損益表")
  10.         xlYear = Mid(.[a3], InStrRev(.[a3], "至") + 1, InStrRev(.[a3], "年") - InStrRev(.[a3], "至"))
  11.         'xlYear : 損益表的年度
  12.         xlMon = Mid(.[a3], InStrRev(.[a3], "年") + 1, InStrRev(.[a3], "月") - InStrRev(.[a3], "年") - 1)
  13.         'xlMon : 損益表的月份
  14.         Set Rng(1) = .[A6,A8,A9,A11,A18:A32,A35:A37]
  15.         ''6個範圍: 銷貨收入,進貨,期末存貨,減:期末存貨,支出,收入 ****
  16.     End With
  17.      For Each A In Rng(1).Areas   'Areas 屬性 傳回 Areas 集合,此集合代表多重範圍中的所有範圍。唯讀
  18.         If InStr(A.Cells(1), "存貨") Then Ay = "存貨" Else Ay = ""
  19.         '例外設定: 期初存貨,期末存貨,的工作表是"存貨??_??"
  20.         ReDim Rng_Ar(1 To A.Count)                      '陣列:元素數 = 費用項目數
  21.         For i = 1 To A.Count
  22.             Sh = Filter(Ar, IIf(Ay = "", Trim(A.Cells(i)), Ay), True)
  23.             If A.Cells(i) = "" Then Sh = Array()   '防呆
  24.             'Filter 函數 傳回一個從零開始的陣列,該陣列包含基於指定篩選準則的一個字串陣列的子集。
  25.             For Each E In Sh
  26.                 With Sheets(E)            '有"費用項目"名稱的 工作表
  27.                     Set Rng(2) = .[A:B].Find(xlYear, lookat:=xlWhole, LookIn:=xlValues, SearchOrder:=xlByRows) '核對年度
  28.                     If Not Rng(2) Is Nothing Then Set Rng(2) = .[a:a].Find(xlMon, lookat:=xlWhole)             '搜尋月份
  29.                     If Not Rng(2) Is Nothing Then
  30.                         X = 1
  31.                         Do
  32.                             If Rng(2).Offset(X).Row > .Cells(.Rows.Count, "D").End(xlUp).Row Then Exit Do
  33.                             If Rng(2).Offset(X) <> Rng(2) And Rng(2).Offset(X) <> "" Then Exit Do
  34.                             X = X + 1
  35.                         Loop
  36.                         'Rng(2).Resize(X, 9) : 月份的範圍
  37.                         If InStr(E, "收入") Then
  38.                             Set Rng(2) = Rng(2).Resize(X, 9).Find("本月合計", lookat:=xlPart) '搜尋本月合計
  39.                             If Not Rng(2) Is Nothing Then Rng_Ar(i) = Rng_Ar(i) + Rng(2).Range("D1")
  40.                             '貸  方 'Range("D1")金額位置:本月合計的第4欄
  41.                         Else
  42.                             If Trim(A.Cells(i)) = "減:期末存貨" Then
  43.                                 With Rng(2).Resize(X, 9)
  44.                                     Rng_Ar(i) = Rng_Ar(i) + .Cells(.Rows.Count, 6)
  45.                                     '借方:當月份<存貨5-6>的F欄的.End(xlDown) :"最後一格 "
  46.                                 End With
  47.                             Else
  48.                                 Set Rng(2) = Rng(2).Resize(X, 9).Find("本月合計", lookat:=xlPart) '搜尋本月合計
  49.                                 If Not Rng(2) Is Nothing Then Rng_Ar(i) = Rng_Ar(i) + Rng(2).Range("C1")
  50.                                 '借方 'Range("C1")金額位置:本月合計的第3欄
  51.                             End If
  52.                         End If
  53.                     End If
  54.                     
  55.                 End With
  56.             Next
  57.         Next
  58.         A.Offset(, IIf(Trim(A.Cells(1)) = "銷貨收入", 2, 1)) = Application.WorksheetFunction.Transpose(Rng_Ar)
  59.         'Transpose(轉置) : 一維陣列(橫式) 轉換為 二維陣列(這裡變一列直式)
  60.     Next
  61. End Sub
複製代碼

作者: iceandy6150    時間: 2014-2-18 22:23

回復 58# GBKEE

感謝G大幫忙

測試都能正常運作

程式相當有深度,要能瞭解可能有點久

再次感謝,Thank you!




歡迎光臨 麻辣家族討論版版 (http://forum.twbts.com/)