針對查詢「autofilter」依關聯性排序顯示文章。依日期排序 顯示所有文章
針對查詢「autofilter」依關聯性排序顯示文章。依日期排序 顯示所有文章

2023年11月15日 星期三

初學者的VBA資料分析 CLASS 3:基本資料分析任務 開始 3.1 數據篩選和排序

 CLASS 3:基本資料分析任務 開始

 3.1 數據篩選和排序

     使用VBA篩選和排序Excel資料。

3.2 計算和公式

     使用VBA錄製巨集和編輯Excel公式。

3.3 簡單的資料視覺化

     創建基本的圖表和圖形。

二、講解:

 3.1 資料篩選和排序

先來看看資料篩選,篩選有常使用篩選功能的每個excel大神,一定都很清楚可以區分為進階篩選跟篩選,都很好用,但我們來用用vba來強化這項應用


先來看篩選,也就是autofilter,其實小編也發過類似的,可以參考看看

從基本的autofilter 這個物件的"方法",來玩玩吧

先來看看autofilter是啥?可以參圖1,其餘EXCEL怎操作不解釋了,偷個懶。

圖1.篩選圖示
小編引用MSDN,MSDN講了好多阿,小編來個入門版教學一下:
快速錄了一個錄製版巨集,如下:


圖2.資料樣貌


Sub 巨集1()

    Selection.AutoFilter
    ActiveSheet.Range("$A$1:$E$13").AutoFilter Field:=3, Criteria1:="=1", _
        Operator:=xlAnd
    ActiveSheet.ShowAllData
    ActiveSheet.Range("$A$1:$E$13").AutoFilter Field:=5, Criteria1:="=1", _
        Operator:=xlAnd
    ActiveSheet.ShowAllData
    
End Sub

節錄一段code來看看   
針對工作表中a1:a13 範圍:ActiveSheet.Range("$A$1:$E$13")
篩選第3:.AutoFilter Field:=3, 

圖3.資料行別對照

篩選條件為1:Criteria1:="=1", 
篩選方式為:Operator:=xlAnd

這樣執行巨集1結果如下圖:
圖4.巨集1運作
圖4說明:先跑b行,然後復原在跑d行。

取消篩選:ActiveSheet.ShowAllData 
執行次行命令後,即恢復篩選前狀態。

以上是篩選的基本入門操作,至於更多的用法,可以參考小編的其他

接著來看排序功能,排序會使用到sort這個方法,老樣子先來個msdn一下
到這不免很多看官會說,啥都msdn,那你整理文章做啥,小編是想,你要先知道官方有技術指導,看無官方版不打緊,來看看小編的入門篇之後,普出一點道理之後,再回去看官方的,或許能幫到一點點忙;畢竟講語法實在是太讓人想滑鼠點上一頁閃了。畢竟網路上也很多人寫類似的,選你好看好懂得,up to you。

言歸正傳,啥是排序,排序就是基本排序資料的一個功能,可以參圖5,其餘EXCEL怎操作不解釋了,偷個懶。
圖5.排序按鈕

小編來個sort入門版教學一下,快速錄了一個錄製版巨集,如下:

錄得滿多的,a行的排序,a、b雙行的排序

某一關鍵參數:大到小,小到大列舉

Sub 巨集2()
'a行的排序 小到大
    ActiveWorkbook.Worksheets("工作表1").Sort.SortFields.Clear
    ActiveWorkbook.Worksheets("工作表1").Sort.SortFields.Add Key:=Range("B2:B13"), _
        SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
    With ActiveWorkbook.Worksheets("工作表1").Sort
        .SetRange Range("A1:E13")
        .Header = xlYes
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With
'a行的排序 大到小
    ActiveWorkbook.Worksheets("工作表1").Sort.SortFields.Clear
    ActiveWorkbook.Worksheets("工作表1").Sort.SortFields.Add Key:=Range("B2:B13"), _
        SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
    With ActiveWorkbook.Worksheets("工作表1").Sort
        .SetRange Range("A1:E13")
        .Header = xlYes
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With
'a行與b行接排序 大到小
    ActiveWorkbook.Worksheets("工作表1").Sort.SortFields.Clear
    ActiveWorkbook.Worksheets("工作表1").Sort.SortFields.Add Key:=Range("B2:B13"), _
        SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
    ActiveWorkbook.Worksheets("工作表1").Sort.SortFields.Add Key:=Range("C2:C13"), _
        SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
    With ActiveWorkbook.Worksheets("工作表1").Sort
        .SetRange Range("A1:E13")
        .Header = xlYes
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With
    
End Sub

小編先說哇,錄了好長一串,來慢慢看過來
用錄製取得的CODE明顯好像跟上面提的SORT MSND內容不一樣

小編在補一下應外一塊MSDN,對照範例與小編錄製的內容
小編:
'a行的排序 小到大

    ActiveWorkbook.Worksheets("工作表1").Sort.SortFields.Clear
    ActiveWorkbook.Worksheets("工作表1").Sort.SortFields.Add Key:=Range("B2:B13"), _
        SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
    With ActiveWorkbook.Worksheets("工作表1").Sort
        .SetRange Range("A1:E13")
        .Header = xlYes
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With

微軟MSDN:
ActiveWorkbook.Worksheets("Sheet1").ListObjects("Table1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet1").ListObjects("Table1").Sort.SortFields.Add _
 Key:=Range("Table1[[#All],[Column1]]"), _
 SortOn:=xlSortOnValues, _
 Order:=xlAscending, _
 DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet1").ListObjects("Table1").Sort
 .Header = xlYes
 .MatchCase = False
 .Orientation = xlTopToBottom
 .SortMethod = xlPinYin
 .Apply
End With

其實除了工作表與儲存格範圍外,範例跟錄製的內容真的長的很像ㄝ,但還是有不同,先回到主軸上排序上
回想一下,透過滑鼠點選操作排序時,有幾個必要設定的地方,分別是要排序那些儲存格,根據那些存格當依據做排序,先來看當使用Sort.SortFields時,主要必設定的部分:
清除篩選: ActiveWorkbook.Worksheets("工作表1").Sort.SortFields.Clear
增加範圍:  ActiveWorkbook.Worksheets("工作表1").Sort.SortFields.Add
設定排序條件範圍:Key:=Range("B2:B13"), _
設定排序條件範圍參數:SortOn:=xlSortOnValues, Order:=xlAscending,DataOption:=xlSortNormal

相關參數就不多再談了,先拉回到排序sort的重點整理一下:
1.資料範圍
2.資料排序依據
3.排序方法選擇(大到小......)
小編想,可能需要寫一篇專文了,呵呵,這邊還是以引入觀念為主。
不然就都泡在程式碼裏頭,引用當兵學長的話,"歐,強哥,這很難吞下的下去說"

小編遇到難免會多補充很多,接下小編端上速成版排序做參考:
3原則
1.資料範圍
2.資料排序依據
3.排序方法選擇(大到小......)

單一排序依據:
activesheet.Range(資料範圍).Sort _
Key1:=activesheet.Range(資料範圍排序依據行別),  _
Order1:=資料排序方式, Header:=xlYes, _
OrderCustom:=1, MatchCase:=False, _
Orientation:=xlTopToBottom, SortMethod  :=xlStroke, _
DataOption1:=xlSortNormal

2組排序依據:
activesheet.Range(資料範圍).Sort _
Key1:=activesheet.Range(資料範圍排序依據行別1),  _
Order1:=資料排序方式1, Header:=xlYes, _
Key2:=activesheet.Range(資料範圍排序依據行別2),  _
Order2:=資料排序方式2, Header:=xlYes, _
OrderCustom:=1, MatchCase:=False, _
Orientation:=xlTopToBottom, SortMethod  :=xlStroke, _
DataOption1:=xlSortNormal

對,就是這樣簡單!!!! 怎我前面一堆廢話 (>__<)

排序 演練一下:

Private Sub CommandButton2_Click()

ActiveSheet.Range("b1:e30").Sort _
Key1:=ActiveSheet.Range("b1"), _
Order1:=xlAscending, Header:=xlYes, _
OrderCustom:=1, MatchCase:=False, _
Orientation:=xlTopToBottom, SortMethod:=xlStroke, _
DataOption1:=xlSortNormal

ActiveSheet.Range("b1:e30").Sort _
Key1:=ActiveSheet.Range("b1"), _
Order1:=xlDescending, Header:=xlYes, _
OrderCustom:=1, MatchCase:=False, _
Orientation:=xlTopToBottom, SortMethod:=xlStroke, _
DataOption1:=xlSortNormal

End Sub



Private Sub CommandButton3_Click()

ActiveSheet.Range("b1:e30").Sort _
Key1:=ActiveSheet.Range("b1"), _
Order1:=xlAscending, Header:=xlYes, _
Key2:=ActiveSheet.Range("c1"), _
Order2:=xlAscending, Header:=xlYes, _
OrderCustom:=1, MatchCase:=False, _
Orientation:=xlTopToBottom, SortMethod:=xlStroke, _
DataOption1:=xlSortNormal

ActiveSheet.Range("b1:e30").Sort _
Key1:=ActiveSheet.Range("b1"), _
Order1:=xlDescending, Header:=xlYes, _
Key2:=ActiveSheet.Range("c1"), _
Order2:=xlDescending, Header:=xlYes, _
OrderCustom:=1, MatchCase:=False, _
Orientation:=xlTopToBottom, SortMethod:=xlStroke, _
DataOption1:=xlSortNormal

End Sub










2023年10月4日 星期三

VBA:使用AutoFilter 批次篩選多筆資料,非多項目歐

 autofilter 滿足多筆資料篩選,如果你是excel使用者,還不知道怎操作vba,那真是可惜

這好用功能配合vba,簡直太神了;當然這時候可能有人說,我可以樞紐阿,阿樞紐分析不用點選嗎?QQ

簡單對比操作一下:


這段功能阿,可以透過錄製方式直接搞定,所以小編不想花太多時間解釋怎樣錄製,而是想表示,怎樣整理這樣的功能呢!!!

 Sheets("工作表1").Range("a1:i" & XX1).AutoFilter Field:=1, Criteria1:=ARRAY, Operator:=xlFilterValues

 Sheets("工作表1").Range("a1:i" & XX1):需要篩選的資料區域
AutoFilter 使用這個方法
Field:設定要篩選的行別
Criteria1:篩選條件,ARRAY非程式碼,ARRAY是簡稱用,在這主要表達要放一個陣列
Operator:篩選作業執行方式

EX:
 Sheets("工作表1").Range("a1:i" & XX1).AutoFilter Field:=1, Criteria1:=ARRAY("1101","1102"), Operator:=xlFilterValues

篩選後剩下1101、1102

下次來看看怎樣篩選:
VBA:使用AutoFilter 批次篩選多筆資料與多項目

2023年8月28日 星期一

錯誤2015 error 2015 application.countif +AutoFilter 溫故知新

 今天小編透過autofilter與application.countif 做資料整理,

怎就application.countif 跑不出來,實在很懊惱ㄝ

明明是很常用的函數說。

抱怨解決不了問題。

先來溫故知新一下:

AutoFilter 篩選日期區間怎做:

在資料區間n1:m1531範圍內透過日期區間做篩選,所以會有兩個Criteria要設定,分別為Criteria1與Criteria2,因為兩個條件都要滿足,所以Operator要加上xlAnd,如此如此這般這般。msdn

ActiveSheet.Range("$N$1:$N$1531").AutoFilter Field:=1, Criteria1:= _

        ">=" & date_test, Operator:=xlAnd, Criteria2:="<=" & end_day

好!!那篩選完成後,要統計一下資料,僅計算篩選後的儲存格範圍(msdn)

這功能稱為XlCellType,很好用,要放在口袋內放好。

透過設置set p_data,僅取用篩選後的儲存格 

 Set p_data = ActiveSheet.Range("m2:m1531").SpecialCells(xlCellTypeVisible)

接下來是統計次數資料的countif函數。

講到這,小編countif 使用到底錯那了?

          Set p_data = ActiveSheet.Range("m2:m1531").SpecialCells(xlCellTypeVisible)

         Set p_data = ActiveSheet.Range("m1:m1531").SpecialCells(xlCellTypeVisible)

錯在設置時把標題放入,所以countif 跑出"錯誤2015"

下次記得別把標題放進範圍內 xd

countif使用,直接調用Application即可

p1 = Application.CountIf(p_data , ">0")

p2 = Application.CountIf(p_data , "<=0")

幫忙計算出大於跟小於等於0的次數,太棒了。

另外篩選範圍也要跟countif計算範圍相同,不然也會跳出"錯誤2015"

ActiveSheet.Range("$N$1:$N$1530").AutoFilter Field:=1, Criteria1:= _

        ">=" & date_test, Operator:=xlAnd, Criteria2:="<=" & end_day

 Set p_data = ActiveSheet.Range("m2:m1531").SpecialCells(xlCellTypeVisible)

反紅為錯誤示範。






2023年8月2日 星期三

sumproduct  v.s autofilter 分析資料時間整理

之前整理過一篇透過sumproduct整理資料的文章,但excel還是有很多好用的工具可以用
但這篇小編不想花太多時間介紹有那些工具。

小編這次先測試不同工具之間的效率差多少。

sumproduct v.s autofilter

資料筆數:約20萬筆
測試要點:不同方法效率比較


sumproduct 運行181秒
autofilter 運行31秒

p.s每個人運行時間應該有差異,但autofilter應該還是比sumproduct快拉。

下一篇來寫寫autofilter教學

 

2025年6月19日 星期四

vba autofilter v.s mysql 查詢與計算語法 比較

 autofilter :是針對既有資料,設定一定程度的條件,此條件可以是單一也可以是多條件後,開始做篩選,但前提是excel本身已準備好資料讓你篩選。

mysql 語法:可以執行最基本的條件查詢、計算後,顯示結果。

比較不同平台,一個是excel,一個是mysql。

其實小編相信很多網路大神一定會說,這還需要比較?

小編想要整理出,不同資料筆數之間差異,當然學習歷程時間也是一個差異,畢竟學excel跟學sql還是有點本質上的不同,但有ai後,似乎有打雞血的up點。

所以小編,以自己常在整理的資料,來做簡單比較:

目前小編每個月會根據台灣上市櫃公司,做產業別資料整理,隨著時間拉長,資料整理期間自然越來越長,就選這個常在整理的資料來比較吧!!

條件:

查詢110/01~110/12的合計15個產業別各月產業別營收

結果:

EXCEL,133.5秒

SQL,76.46秒;

小編進一步改成直接查詢105/01~114/05拉大13倍查詢範圍,變成71.203,決定在測一次70.698。

比較後,小編呵呵笑了,原來比較後,也確認了是EXCEL寫資料表時間最耗時,

對SQL來說擴大13倍查詢根本不是問題。

小編就不測試EXCEL擴大13倍後,需要花費多少時間了。

也有另外一個可能,就是小編寫的AUTOFILTER 效率太差,應該拿去效率最好的方法去PK阿。

QQ。

方法有很多,熟悉有幾個,能學好多個,答案靠己尋。


附上小編自己的VBA:(很差,參考)

SUB C1' SQL

 shell "powercfg.exe setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c " '高效能 

On Error GoTo LINE1

ActiveSheet.Range("A:G").Clear    

S1 = ActiveSheet.Range("aa2000").End(xlUp).Row

data = INCOME_SQL_SUM_catrgory("105/01", "114/05")

For i = LBound(data, 1) To UBound(data, 1)

    For j = LBound(data, 2) To UBound(data, 2)

        If IsNull(data(i, j)) Then data(i, j) = "" ' 替換Null為空字串

        If IsNumeric(data(i, j)) Then data(i, j) = CStr(data(i, j)) ' 統一轉文字型態

    Next j

Next i

ActiveSheet.Range("A1").Resize(UBound(data, 2), UBound(data, 1) + 1) = WorksheetFunction.Transpose(data)

For i = 1 To UBound(data, 2) + 1 Step 1             

              If ActiveSheet.Range("C" & i + 1) <> "" And ActiveSheet.Range("C" & i + 1) <> "" And _

              ActiveSheet.Range("C" & i + 1) <> 0 And ActiveSheet.Range("C" & i + 1) <> 0 Then            

            ActiveSheet.Range("F" & i + 1).Value = (val(ActiveSheet.Range("C" & i + 1).Value) - _

            val(ActiveSheet.Range("D" & i + 1).Value)) / val(ActiveSheet.Range("D" & i + 1).Value)                 End If

Next    

TOPIC = Array("產業別", "月份", "當月營收", "去年當月營收", "新高家數", "年增減(%)")

ActiveSheet.Range("A1:F1").Insert

ActiveSheet.Range("A1:F1") = TOPIC          

s3 = ActiveSheet.Range("B1000000").End(xlUp).Row   

     ActiveSheet.Range(ActiveSheet.Cells(1, 1), ActiveSheet.Cells(s3, 7 + 2)).Sort key1:=ActiveSheet.Range("a" & ":" & "a"), order1:=xlAscending, Header:=xlYes, _

        OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, SortMethod:=xlStroke, DataOption1:=xlSortNormal                         

                           Beep                           

                           Beep                           

                           Beep                           

                             MsgBox Timer - T

                            Exit Sub

LINE1:

MsgBox "ERROR"                            

                            Resume

END SUB


SUB C2 'AUTOFILTER

 Application.ScreenUpdating = False

  Application.DisplayStatusBar = False

  Application.Calculation = xlCalculationManual

  Application.EnableEvents = False

  ' Note: this is a sheet-level setting.

 ' ActiveSheet.DisplayPageBreaks = False

SOURCE = Excel.ActiveWorkbook.Name

 Shell "powercfg.exe setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c " '高效能

 On Error GoTo LINE1

Sheets("產業別").Range("A:E").Clear    

S1 = Sheets("產業別").Range("aa2000").End(xlUp).Row

 list_data = Sheets("產業別").Range("aa1:aa" & S1) 

 list_data = 移除重複(list_data) 

 S1 = Sheets("產業別").Range("z2000").End(xlUp).Row 

  list_data2 = Sheets("產業別").Range("z1:z" & S1) 

 list_data2 = 移除重複(list_data2) 

  Sheets("產業別").Range("a:e").Clear

ADD = 2

TOPIC = Array("產業別", "月份", "當月營收", "去年當月營收", "年增減(%)")

Sheets("產業別").Range("A1:E1") = TOPIC

 SOURCE = Excel.ActiveWorkbook.Name

For j = LBound(list_data2) To UBound(list_data2) Step 1 '(J) <> ""

            Sheets("月營收").Activate            

            'XX1 = Application.CountA(Sheets("月營收").Range("A:a")) '.End(xlUp).Row     

            XX1 = Sheets("月營收").Range("B1000000").End(xlUp).Row

                        Sheets("月營收").Range("$a$1:$J$" & XX1).AutoFilter Field:=3, Criteria1:= _

                                                                        "=" & list_data2(j) '

                         For O = LBound(list_data) To UBound(list_data) Step 1

                           Sheets("月營收").Range("$a$1:$J$" & XX1).AutoFilter Field:=4, Criteria1:= _

                                                                        "=" & list_data(O) '   

                                        Set 當月營收 = Sheets("月營收").Range("E1:E" & XX1).SpecialCells(xlCellTypeVisible)

                                        Set 當月營收12高 = Sheets("月營收").Range("L1:L" & XX1).SpecialCells(xlCellTypeVisible)

                                        Set 去年當月營收 = Sheets("月營收").Range("G1:G" & XX1).SpecialCells(xlCellTypeVisible)

                                         Sheets("產業別").Cells(ADD, 1).Value = list_data2(j)

                                         Sheets("產業別").Cells(ADD, 2).Value = list_data(O)

                                        Sheets("產業別").Cells(ADD, 3).Value = Application.Sum(當月營收)   

                                        Sheets("產業別").Cells(ADD, 4).Value = Application.Sum(去年當月營收)

                                        Sheets("產業別").Cells(ADD, 6).Value = Application.Sum(當月營收12高)

                                        On Error Resume Next

                                        Sheets("產業別").Cells(ADD, 5).Value = (Sheets("產業別").Cells(ADD, 3).Value - Sheets("產業別").Cells(ADD, 4).Value) / Sheets("產業別").Cells(ADD, 4).Value

                                         On Error GoTo LINE1

                                         ADD = ADD + 1

                            Next

                            Sheets("月營收").AutoFilterMode = False

                            Next

              Windows(SOURCE).Activate

              income_row_年增率 = Sheets("產業別").Range("a" & "65536").End(xlUp).Row

             Set myRange_R = Sheets("產業別").Range("A1:E" & income_row_年增率)

            myRange_R.RemoveDuplicates Columns:=Array(1, 2), Header:=xlYes

             Set myRange_R = Nothing

     Application.ScreenUpdating = True

  Application.DisplayStatusBar = True

  Application.Calculation = xlCalculationAutomtic

  Application.EnableEvents = True


END SUB



2020年12月28日 星期一

VBA:AutoFilter應用:找特定時間區間,股價最高與最低值(YAHOO FINANCE CSV為例)

 RANGE有相當多的屬性跟方法,AutoFilter即為RANGE的方法之一,MSDN查詢結果,小小編由YAHOO FINANCE下載了某間公司的過去歷史股價,合計5200多筆收盤價資料,以此案例來實際操作一。範例下載

 P.S範例資料有略為簡化。

如果你經常在用YAHOO FINANCE下載資料來用,可以看看怎操作😀

至於批次找出各公司的最高最低價,有空在單獨寫一篇。

一、目的:找出該公司每一年最高與最低股價。

圖1.原始資料

二、IPO發想與評估:

每一年,所以有期間限制、最高最低價內建函數可以解決、是否要使用陣列的方式堆壘資料

2.1 IPO拆解步驟:

A.資料來源:在A到F行,A行為日期,B到E行為股價資料。

         B.怎處理: 

1.觀察資料與問題:

(1)資料為連續的,沒有空白,有完整日期標示可以免除資料前處理。

(2)現況資料有幾年?怎知道是那一年開始的?

(3)找出最大與最小分別可以透過MAX與MIN等內建函數完成。

(4)透過內建函數MAX與MIN,但對應的範圍怎設定才能是特定期間? 

2.滿足問題:

(1)有幾年這部分,因為資料是連續的,可以透過取的最後一筆資料跟第一筆資料來判斷需要執行幾年的期間,來設計迴圈。

(2)內建函數範圍設定這部分,回想到VBA:Cells.SpecialCells 簡單應用+ 資料排序一文,透過設定為xlCellTypeConstants方式來取的位置即可解決。

C.輸出 :

把年份找出來後,新增一頁工作表名為OUT,做各年份最高最低股價結果顯示與儲存用。 

2.2 評估:

每一年,所以有期間限制:OK

最高最低價內建函數可以解決:OK

是否要使用陣列的方式堆壘資料:股價不用天天整理最高最低,所以免用陣列。

三、動作寫:

     AutoFilter 簡單說明:

 Sheets("還原股價").Range("$A$1:$f$" & END_ROW).AutoFilter Field:=1, Criteria1:= _

           ">=" & year_begin & "/1/1", Operator:=xlAnd, Criteria2:="<=" & year_begin & "/12/31" 

Field:設定篩選的條件是第幾行。

Criteria1、Criteria1:因為是區間,所以要設定2個條件。

Operator:篩選類型設定,因為有兩個條件所以設為xlAnd。

year_begin:是透過迴圈控制的篩選變數,配合 "/1/1"與"/12/31" 組合成年頭與年末的篩選條件。

先作一個ACTIVEX按鈕插入以下VBA:


圖2.按鈕一測試結果


小小編突發奇想,想要知道股價日期,追加修改了一下:

在作一個ACTIVEX按鈕插入以下VBA: 

圖3.按鈕二測試結果


2021年7月23日 星期五

VBA:歷史資料計算本益比

首先準備資料:歷史股價(任意門YAHOO FINANCE),EPS:這部分資料各大卷商都有得查。

主題:小編主要是透過RANGE物件的方法AUTOFILTER與MAX、MIN等內建函數功能來完成本益比高低點歷史資料計算。

本益比簡單快入說明,就是股價/EPS=本益比;本益比高點=股價高點計算結果、本益比低點=股價低點計算結果。哈哈好廢話歐😁

來看VBA怎寫:

小編直接用YAHOO FINANCE下載的檔案直接新增一頁工作表1,然後在列1輸入年份,2020~2015;ˋ接著作一個按鈕插入以下CODE內容。

CODE:



結果:
圖1.
P.S框線是手動加的

想想怎樣自動做完1600多家公司哩!!!!😅😅😅
小編目標每天自動算完作本益比分析投資用~~~吃飽太閒。




2025年12月19日 星期五

VBA 資料分析教學:DAY 7

 假設你在Excel的Sales工作表中有以下欄位:

A欄:日期(日期)

B欄:業務員(營業員)

C欄:金額 (Amount)

目標:以VBA自動計算業務當月總銷售金額,並輸出至Summary工作表。



Sub SalesSummaryBySalesperson()

    Dim wsSrc As Worksheet

    Dim wsDst As Worksheet

    Dim lastRow As Long

    Dim dict As Object

    Dim i As Long

    Dim name As String

    Dim amt As Double

    Dim key As Variant

    Dim outRow As Long

    

    ' 來源與目的工作表

    Set wsSrc = ThisWorkbook.Worksheets("Sales")

    Set wsDst = ThisWorkbook.Worksheets("Summary")

    

    ' 找到來源資料最後一列(假設以 B 欄業務名稱為基準)

    lastRow = wsSrc.Cells(wsSrc.Rows.Count, "B").End(xlUp).Row

    

    ' 使用 Scripting.Dictionary 做彙總

    Set dict = CreateObject("Scripting.Dictionary")

    

    ' 從第 2 列開始,假設第 1 列為標題

    For i = 2 To lastRow

        name = wsSrc.Cells(i, "B").Value

        amt = wsSrc.Cells(i, "C").Value

        

        If dict.Exists(name) Then

            dict(name) = dict(name) + amt

        Else

            dict.Add name, amt

        End If

    Next i

    

    ' 清空 Summary 工作表舊資料

    wsDst.Cells.Clear

    

    ' 輸出標題

    wsDst.Range("A1").Value = "業務員"

    wsDst.Range("B1").Value = "總銷售額"

    

    ' 將彙總結果寫回工作表

    outRow = 2

    For Each key In dict.Keys

        wsDst.Cells(outRow, "A").Value = key

        wsDst.Cells(outRow, "B").Value = dict(key)

        outRow = outRow + 1

    Next key

    

    ' 簡單格式化:加上千分位以及粗體標題

    wsDst.Range("A1:B1").Font.Bold = True

    wsDst.Columns("A:B").AutoFit

    wsDst.Range("B2:B" & outRow - 1).NumberFormat = "#,##0"

    

End Sub


重點解說

使用Scripting.Dictionary“鍵值名稱”,鍵是業務員,值是銷售額,適合做總結分析。號

透過迴圈讀取每列數據,根據業務員名稱累加金額,最後批量輸出到匯總工作表,可避免在迴圈中間隙出現儲存格造成低落。號


這個寫法之後可以延伸:

增加月份條件,只彙總指定月份。

改為依「產品別」或「客戶別」做匯總。

安排AutoFilter或AdvancedFilter前處理資料重新匯總。

 

2021年8月15日 星期日

VBA+股票:外資投信籌碼(8/14)

以下是無聊亂整理,不作為股票投資參考。

8/14週:

圖1.外資

圖2.投信



選金融保險業的外資部分,進一步分析看看原始是怎回事  GO!

圖3.投信整理

原來外資在買的是這幾間歐!!!作筆記作筆記;那投信勒??

圖.外資整理

把投信也拉進來看看,疑某一檔買不少歐,ㄏㄏ。

 VBA語法簡易教學:

透過EXCEL內建函數功能,來滿足自動計算:
大致整理資料作業流程是:先篩選資料>指定資料(SpecialCells)>用內建函數計算
      
XX1 = Sheets("工作表1").Range("A65536").End(xlUp).Row
            
Sheets("工作表1").Range("$a$1:$l$" & XX1).AutoFilter Field:=1, Criteria1:= "=" & list_data(J) 
'list_data(J)陣列建有篩選字串資料
Set 外資5天增持張數 = Sheets("工作表1").Range("g1:g" & XX1).SpecialCells(xlCellTypeVisible)
Sheets("工作表3").Cells(2, J + 1).Value = Application.Sum(外資5天增持張數)








2022年4月30日 星期六

VBA:取消篩選(Autofilter、AdvancedFilter )

執行c_3 副程式即取消篩選狀態

Sub C_3() '篩選與復原

  Dim ws As Worksheet

    Set ws = ThisWorkbook.ActiveSheet

    With ws

        If .FilterMode Then

            .ShowAllData

        End If

    End With

    Set ws = Nothing

End Sub

2025年10月26日 星期日

VBA:上萬筆 Excel 資料別怕卡卡,這樣做超快^^!

這篇文章主要分享如何用 VBA 分析及篩選海量資料,並透過資料結構優化大幅提升效率。

如何用 VBA 效率處理 5 萬筆資料

最近在跑分析流程時,常常需要用到約 5 萬筆資料來做模擬。這些資料是額外產生的,無法直接從歷史 SQL 查詢,所以每次都要重新計算,資料範圍從 104 年到 114 年,簡稱「A 資料」。

熟悉 VBA 的朋友都知道,Excel VBA 內建像是 AUTOFILTER 等工具,的確能輕鬆篩選數據,但量一旦逼近幾萬筆,效能就明顯下降。舉個例子,如果每次用 Excel 篩選 5 萬筆資料要花 30 秒,分析 10 年的單一條件就得花 10 × 30 = 300 秒,也就是 5 分鐘。假如有多個條件,更是用 N × 300 秒計算,真是讓人耗不起。

或許硬體升級是個解,但預算不是人人都有,小編認為這也是很適合拿來談「怎麼處理海量資料」的題材。實際上 VBA 本身分析功能不弱,只是網路上很多 YT 評論說 VBA 限制多、容易撞記憶體、資料多容易閃退。其實你懂得用好現有資源,小工具還是能發揮大作用,不要輕易放棄已經花錢買的軟體,也要珍惜自己的資金!

分解條件與資料分割

小編的篩選條件主要分成兩大類:

·        概念股股票:共約 200 種組合

·        財報特定指標:約 20 個條件

如果全部都用 A 資料來跑,200 × 20 × 5 萬,真的對不起自己的時間。解決方法就是,先把海量的 A 資料,轉成「只要用的範圍」,簡稱「B 資料」。例如 PCB 概念股大約 20 檔,則 A 資料只挑出這 20 檔股票 10 年的數據,變成 B 資料,資料量就降到 20 × 10 = 200 筆。

再加上 20 個指標條件,總共只要分析 200 × 20 = 4000 筆,效率提升到「秒殺」級。A 資料轉 B 資料前置處理約 30 秒,後續 10 年 × 20 個條件幾乎都在 1 秒內完成:

·        前置處理:30 秒

·        單條件分析:1 秒 × 20 = 20 秒

·        總共:約 50 秒

原本 20 × 300 = 6000 秒,分群後只花 40 秒,效率差異 40 / 6000 

與原始做法相比,假設 20 個條件都用原法,總共要 6,000 秒(20 × 300 秒),經由分群,只需 50 秒,效率提升超過百倍,僅耗時 0.83%。

資料分割才是效率王道

重點就是:資料很重要,但「要處理的」資料更重要!只要分群精準,把不用的資料先篩掉,大大節省運算和等待的時間。這是分析海量資料的致勝絕招,也值得大家在日常工作實際應用。這樣你可以更充分解釋背景流程、讓篩選公式跟單位更清楚,也讓效率提升的呈現更具衝擊力!


指數變化(2026.07.31) 開始透過AI做整理

 指數變化(2026.07.31) 開始透過AI做整理 一、上周焦點:  7/27 美國 耐久財訂單(6 月) - 全部耐久財訂單月增 0.3%,結束前一月 -4.0% 的跌勢,增幅低於市場預期約 1.8%。   - 核心耐久財(扣除運輸設備)約月增 0.6%,顯示一般設備需求溫...