[VBA] 自動爬取上市櫃股票近16年「 歷史本益比 」

何謂「 歷史本益比 」?

※「 歷史本益比 」: 英文 ( Trailing Price-to-Earnings ),簡稱 : Trailing P/E。意思是將 目前股價 除以 過去12個月EPS總額,所求得之數值,即為 : 歷史本益比

( PS. 有關本益比的介紹與解說,這裡不多贅述,請參考上一篇文章 : [VBA] 自動上網爬取「 本益比 」– 找出被低估的股票。文中也提供了 本益比 的計算公式。)

[ 本益比 / 計算公式 ] :
本益比

歷史本益比 的計算方式 : 最簡單就是將個股的 年度股價 除以 年度公布的EPS(每股盈餘)。( PS. 年度股價 則是 年底的收盤價。)

如何抓取「 歷史本益比 資料 ?

◎ 相同於上篇文章「 本益比 」的擷取方式,不同之處僅在於 日期 的選取。本文同樣以抓取上市櫃股票的 歷史本益比 資料來說明。
[ 1 ] : 證交所 : 意指抓取上市公司股票之歷史本益比。
[ 2 ] : 櫃買中心 : 意指抓取上櫃公司股票之歷史本益比。

證交所 : 查詢網址 — 如下 : https://www.twse.com.tw/zh/trading/historical/bwibbu-day.html
本益比

櫃買中心 : 查詢網址 — 如下 : https://www.tpex.org.tw/web/stock/aftertrading/peratio_analysis/pera.php?l=zh-tw
本益比

( PS. 證交所與櫃賣中心為了方便投資者查詢個股盤後相關資料,不僅提供當日個股 本益比/ 殖利率/ 股價淨值比 的查詢資料,同時也能查詢近18年的歷史資料。)

VBA 實作 — 爬取年度/本益比資訊

◎ 上市櫃公司既然提供了近18年的本益比資訊,理所當然要將其下載,才方便於探索個股歷史本益比的趨勢變化。

[ 爬取歷史本益比的操作步驟 ] :
[ 1 ] : 製作股票代號表頭
[ 2 ] : 爬取個股本益比
[ 3 ] : 整理年度本益比資料

製作股票代號表頭

※「 表頭 」: 是表格的開頭部分,用於資料歸類的說明,也可說是表格資料的名字。
◎ 表頭畫面 — 參考下圖。


[ 製作基準股票代號的目的 ] :
※ 主要是歷年來的上市櫃公司,均有增減,所以必須以最新的上市櫃股票代號,作為基準,再與歷年的股票代號作比對,找出16年來新上市的股票代號,加以處理並附於其值,如此便能整理出完整的上市櫃股票歷史本益比資料。

[ 舉例 ] :
◎ 以 2007年為例 — 上市櫃股票總合為 : 1236 檔,至今 2023年股票總和 : 1775 檔,所以最新的 1775 檔股票代號,便是基準。

※ 了解其設計目的,便開始爬取上市與上櫃公司的股票資料,製作全股票代號的基準表頭。

爬取上市公司年度/本益比

※ 證交所(上市公司) / 當日本益比查詢網址 : https://www.twse.com.tw/zh/trading/historical/bwibbu-day.html
◎ 網頁畫面 — 參考下圖。
歷史本益比

[ 操作步驟 ] :
[ 1 ] : 輸入證交所本益比網址 : https://www.twse.com.tw/zh/trading/historical/bwibbu-day.html。進入上述畫面。
[ 2 ] : 輸入年度查詢日期 : 將原預設日期改為歷年年底日期。( PS. 依上例,由於民國111年12月31日為 : 星期六 (未開盤),故改為搜尋 : 12月30日。)
[ 3 ] : 點擊查詢 : 選定好查詢日期後,務必要點選 : 查詢 (按鍵)。( PS. 個股盤後資料才會更新顯示。)
[ 4 ] : 選擇顯示筆數 : 原預設筆數為 : 10筆。若想改為顯示全部的股票資料,則將其下拉式選項改為 : 全部,即可。
[ 5 ] : 點選 列印 / HTML : 游標移至 列印 / HTML 位置,按 : 滑鼠左鍵,系統會自動開分頁,顯示查詢的本益比網頁資料。網址為 : https://www.twse.com.tw/rwd/zh/afterTrading/BWIBBU_d?date=20221230&selectType=ALL&response=html,此網址便是之後VBA錄製巨集時,所需的網址資料。

[ 參考畫面 / 上市公司股票歷史本益比 ] :

錄製巨集 — 下載證交所歷史本益比資料

[ 操作步驟 / 錄製巨集 ] :
[ A ] : 錄製巨集 : 請參考 錄製巨集(舊版) 內的錄製步驟,錄製完,會在新增的工作表( 歷史TSE本益比 ),產生當日收盤後全部個股的本益比資料。( PS. 開頭定位在 A1。)

◎ 在製作過程中,須注意的三點 :
1. 新增活頁簿,設定檔名 : 爬取歷史本益比資料.xlsm
2新增工作表,設定名稱 : 歷史TSE本益比
3. 從WEB(舊版) 抓取資料時,URL 網址輸入框內,需輸入剛擷取出來的本益比資料網址 :
https://www.twse.com.tw/rwd/zh/afterTrading/BWIBBU_d?date=20221230&selectType=ALL&response=html

[ B ] : 證交所擷取出來的 歷史本益比 / 盤後 表格資料,存放於 歷史TSE本益比 工作表內,顯示如下 :


[ 程式碼 / 爬取上市公司歷史本益比 ] :
Sub 爬取上市公司歷史本益比資料()
    With ActiveSheet.QueryTables.Add(Connection:= _
        "URL;https://www.twse.com.tw/rwd/zh/afterTrading/BWIBBU_d?date=20221230&selectType=ALL&response=html" _
        , Destination:=Range("$A$1"))
'        .CommandType = 0
'        .Name = "BWIBBU_d?date=20230810&selectType=ALL&response=html"
        .FieldNames = True
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .BackgroundQuery = True
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .WebSelectionType = xlAllTables
        .WebFormatting = xlWebFormattingNone
        .WebPreFormattedTextToColumns = True
        .WebConsecutiveDelimitersAsOne = True
        .WebSingleBlockTextImport = False
        .WebDisableDateRecognition = False
        .WebDisableRedirections = False
        .Refresh BackgroundQuery:=False
        .Delete
    End With
End Sub

[ 注意 ] : 使用舊版爬取出來的資料,會在執行 .CommandType = 0 時,出現錯誤訊號。此時,只要將其註解( ) 掉,就沒事了。
( PS. 另外,在程式後段加上 .Delete (切斷連線),這樣系統就不會造成連線膨脹,導致當機。)

爬取上櫃公司年度/本益比

櫃買中心(上櫃公司) / 當日本益比查詢網址 : https://www.tpex.org.tw/web/stock/aftertrading/peratio_analysis/pera.php?l=zh-tw
◎ 網頁畫面 — 參考下圖。


[ 操作步驟 ] :
[ 1 ] : 輸入櫃買中心本益比網址 : https://www.tpex.org.tw/web/stock/aftertrading/peratio_analysis/pera.php?l=zh-tw
[ 2 ] : 輸入年度查詢日期 : 將原預設日期改為歷年年底日期。( PS. 依上例,由於民國111年12月31日為 : 星期六 (未開盤),故改為搜尋 : 12月30日。歷史本益比查詢,可追朔至民國96年之本益比資料。)
[ 3 ] : 點選 列印 / HTML : 游標移至 列印 / HTML 位置,按 : 滑鼠左鍵,系統會自動開啟分頁,顯示查詢的本益比網頁資料。網址為 : https://www.tpex.org.tw/web/stock/aftertrading/peratio_analysis/pera_result.php?l=zh-tw&o=htm&d=111/12/30&c=&s=0,asc,此網址便是之後VBA錄製巨集時,所需的網址資料。

[ 參考畫面 / 上櫃公司股票歷史本益比 ] :

改寫程式碼 — 爬取上櫃公司歷史本益比資料

※ 取得上櫃公司的資料網址後,便可直接改寫上市公司的本益比程式碼,用於爬取上櫃公司之本益比資料。
( PS. 因二程式碼皆相同,唯獨爬取的目標網址不同而已,故將其網址修改,便能取得上櫃公司的本益比資料。)

[ 操作步驟 / 改寫程式碼 ] :
1再新增一工作表,設定名稱 : 歷史OTC本益比
2. 複製一組 爬取上市公司歷史本益比資料 程式碼,將其名稱與爬取網址改寫成 : https://www.tpex.org.tw/web/stock/aftertrading/peratio_analysis/pera_result.php?l=zh-tw&o=htm&d=111/12/30&c=&s=0,asc

◎ 上櫃公司擷取出來的 本益比 / 盤後 表格資料,存放於歷史OTC本益比 工作表內,顯示如下 :


[ 程式碼 / 爬取上櫃公司歷史本益比 ] :
Sub 爬取上櫃公司歷史本益比資料()
    With ActiveSheet.QueryTables.Add(Connection:= _
        "URL;https://www.tpex.org.tw/web/stock/aftertrading/peratio_analysis/pera_result.php?l=zh-tw&o=htm&d=111/12/30&c=&s=0,asc" _
        , Destination:=Range("$A$1"))
'        .CommandType = 0
'        .Name = "BWIBBU_d?date=20230810&selectType=ALL&response=html"
        .FieldNames = True
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .BackgroundQuery = True
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .WebSelectionType = xlAllTables
        .WebFormatting = xlWebFormattingNone
        .WebPreFormattedTextToColumns = True
        .WebConsecutiveDelimitersAsOne = True
        .WebSingleBlockTextImport = False
        .WebDisableDateRecognition = False
        .WebDisableRedirections = False
        .Refresh BackgroundQuery:=False
        .Delete
    End With
End Sub

手動整合上市櫃股票代號

※ 取得上市/上櫃公司股票盤後資料後,便可將其 股票代號 整合/排序。

[ 手動整合步驟 ] :
1. 新增工作表,設定名稱 : 股票代號
2. 複製 上市公司之股票資料 至 股票代號 工作表 A1 開頭位址。
3. 複製 上櫃公司之股票資料 至 股票代號 工作表 A行 資料最下方之空白位址。

◎ 上市/上櫃公司之股票資料整合圖表 :


[ 注意 / 刪除上櫃公司之最後一筆資料 ]
※ 複製完,上市/櫃公司之股票資料後,要特別注意一件事,就是刪除上櫃公司的最後一筆 : 共807筆 的資料記錄。

( PS. 雖說對之後的排列,不會造成影響,但還是加以刪除,以避免未知的錯誤情況發生。)

4. 將所有股票資料 — 格式化為表格


[ 格式化為表格 之步驟 ] :
[ 1 ] : 選取所有股票資料。
[ 2 ] : 點選 — 格式化為表格 按鈕。
[ 3 ] : 選取想顯示的表格樣式。
[ 4 ] : 選取樣式後,會出現 建立表格 視窗,直接按 : 確定,即可。
( PS. 因步驟[ 1 ] 已將資料選取,故資料來源會自動顯示選取範圍,無需再做更動;另外因資料裡有標題,所以將 我的表格有標題 打勾。)

5. 將股票代號做 從小到大 的排序動作。( PS. 依照下圖步驟操作,即可。)

爬取歷年個股本益比

※ 基準股票代號表頭完成後,便開始設計抓取歷年來的股票歷史本益比資料。上市公司提供從民國 94年前的資料記錄,上櫃公司則提供從民國 96年開始的資料,為求一致性,故由民國 96年(2007年)開始抓取個股本益比數據。

[ 歷年本益比爬取方式 ] :
◎ 以年度方式來抓取本益比時,時間則訂於每年年底的日期(12/31日),由 2007年開始至 2022年止。
◎ 新增2個新工作表,名稱設定如下 : 
[ 1 ] : 歷史本益比整合 : 存放整合上市櫃個股年度本益比資料。
[ 2 ] : 年度本益比 : 存放所有上市櫃個股年度本益比之歷史資料。

    
    [ 程式碼 / 歷年本益比爬取方式 ] :
    Sub 抓取年度歷史本益比資料()
    Dim xYear As Integer
        For xYear = 2007 To 2022
            hisDate = Trim(Str(xYear) & "1231")  ' 利用 Trim 刪除字串前後空白 !
            Sheets("歷史本益比整合").[C2:Z3000].ClearContents
            Call 爬取個股本益比資料
            Call 整理年度本益比資料
        Next
    End Sub

[ 語法解析 ] :
For xYear = 2007 To 2022 : 利用 For ~ Next 迴圈,抓取 2007年 ~ 2022年 的本益比資料。
hisDate = Trim(Str(xYear) & “1231”) : 首先以上市公司抓取本益比的日期格式( 20071231 )來設定。為避免字串連結出現空格現象,則利用 Trim函式,來清除字串的前後空格。
Sheets(“歷史本益比整合”).[C2:Z3000].ClearContents : 清除 歷史本益比整合 工作表內的舊有資料,避免資料錯誤。
Call 爬取個股歷年本益比資料 : 呼叫副程式( 爬取個股歷年本益比資料 )。

爬取個股本益比

修改程式碼日期變數

※ 首先將 爬取上市/櫃公司歷史本益比 程式碼的 日期 部分,修改成 變數,以達到自動爬取的目的。

※ 程式碼 — 語法修改如下 :
[ 上市公司 / 原網址語法 ] :
◎ https://www.twse.com.tw/rwd/zh/afterTrading/BWIBBU_d?date=20221230&selectType=ALL&response=html
[ 修改後 ] :
→ https://www.twse.com.tw/rwd/zh/afterTrading/BWIBBU_d?date= ” & hisDate & “&selectType=ALL&response=html

[ 上櫃公司 / 原網址語法 ] :
◎ https://www.tpex.org.tw/web/stock/aftertrading/peratio_analysis/pera_result.php?l=zh-tw&o=htm&d=111/12/30&c=&s=0,asc
[ 修改後 ] :
chineseDate = Int(Left(xToday, 4) – 1911) & “/” & Mid(xToday, 5, 2) & “/” & Right(xToday, 2) ‘ 文字組合成 — 111/12/30
→ https://www.tpex.org.tw/web/stock/aftertrading/peratio_analysis/pera_result.php?l=zh-tw&o=htm&d=” & chineseDate & “&c=&s=0,asc

判別12/31日是否為交易日

※ 一開始設定搜尋的日期為 : 12/31日,但並不是每個年度的 12/31日都是交易日,所以必須給個 IF判斷式,來判別是否有顯示本益比資料,若 : 無資料( ” “ ),則將日期往前移一天,再重新執行爬取本益比的動作。

    
    [ 程式碼 / 判別是否為交易日 ] :
    If [A1] = "" Then
        hisDate = Trim(Str(Int(hisDate) - 1))
        Call 爬取個股本益比資料
        Exit Sub
    End If

[ 語法解析 ] :
If [A1] = “” Then : 判別工作表內的A1位置,是否為 : ” “ (無資料)。
hisDate = Trim(Str(Int(hisDate) – 1)) : 將搜尋日期往前移一天。( 解 : 先將文字變數 : hisDate ( “20111231” ),轉成數值( Int ),然後 -1 = 20111230,再轉回文字( Str ),再用 Trim 函式去除字串前後空白,避免資料錯誤。)
Call 爬取個股本益比資料 : 重新執行 Sub 副程式 : 爬取個股本益比資料
Exit Sub : 務必要加上 Exit Sub (中斷程式),才不會因為變換日期,重新執行(Call)爬取程式,而導致重複抓取本益比資料。

整合本益比資料

※ 藉由 爬取歷史本益比 程式碼,取得上市/上櫃公司股票本益比資料後,便可將其整合/排序。

[ 整合步驟 ] :
1. 複製 上市公司之本益比資料( A ~ E欄 ) 至 歷史本益比整合 工作表 A1 開頭位址。
2. 複製 上櫃公司之本益比資料( A ~ C欄 ) 至 歷史本益比整合 工作表 A行 資料最下方之空白位址。

◎ 上市/上櫃公司之資料整合圖表 :

    
    [ 程式碼 / 複製上市公司本益比資料 ] :
        Sheets("歷史TSE本益比").Select  ' 切換至"歷史TSE本益比"工作表。    
        Range("A2:E1000").Copy  ' 拷貝資料 : 從 A2 ~ E1000欄位的所有資料。
        Sheets("歷史本益比整合").[A1].PasteSpecial Paste:=xlPasteAll  ' 將拷貝資料 -- 貼於"歷史本益比整合"工作表A1欄位開始的位置。
        Sheets("歷史本益比整合").Columns("C:D").Delete  ' 再將"歷史本益比整合"工作表中C與D行的資料刪除。

    [ 程式碼 / 複製上櫃公司本益比資料 ] :
        Sheets("歷史OTC本益比").Select  ' 切換至"歷史OTC本益比"工作表。    
        Range("A3:C1000").Copy  ' 拷貝資料 : 從 A3 ~ C1000欄位的所有資料。
        newRow = Sheets("歷史本益比整合").[A1].End(xlDown).Row + 1  ' 找出"歷史本益比整合"工作表A行最後一列之列號 + 1 = 最新一空白列。
        Sheets("歷史本益比整合").Range("A" & newRow).PasteSpecial Paste:=xlPasteAll  ' 將拷貝資料 -- 貼於"歷史本益比整合"工作表A行往下找最新空白列的位置。

[ 提醒注意 ] :
※ 當你在執行 2007上市公司本益比資料抓取時,你會發現抓取的本益比資料是錯誤的,原因是 : 2007年 ~ 2016年本益比的行號位置與現在不同,所以會產生資料抓取錯誤。

[ 本益比 / 2007年與現在的行號位置 ] :


[ 解決方法 ] :
◎ 程式碼加入 IF 判斷式,來分辨本益比的行號位置,藉以抓取正確的本益比資料。

    
    [ 程式碼 / 複製上市公司本益比資料 -- 修正版 ] :
    Sheets("歷史TSE本益比").Select
    If [C2] = "本益比" Then
        Range("A2:C1000").Copy
        Sheets("歷史本益比整合").[A1].PasteSpecial Paste:=xlPasteAll
    Else
        Range("A2:E1000").Copy
        Sheets("歷史本益比整合").[A1].PasteSpecial Paste:=xlPasteAll
        Sheets("歷史本益比整合").Columns("C:D").Delete
    End If

整理年度本益比資料

※ 年度上市櫃股票本益比資料完成抓取後,便開始進行股票代號比對動作,以擷取個股之本益比資料。

[ 提醒 ] :
☆ 在進行股票代號比對動作前,必須先在年度本益比工作表中手動建立最新年度的股票代號表頭,這樣才能確保歷史本益比資料,抓取了所有上市櫃股票代號。

[ 年度本益比之股票代號表頭 ] :


[ 代號比對後的處理方式 ] :
◎ 將 基準的股票代號 與 年度的股票代號 作比對查詢,若基準代碼存在於年度代碼,則擷取年度本益比資料;若不存在,表示此檔股票尚未上市,故將本益比,設為 : 0

    
    [ 程式碼 / 整理年度本益比資料 ] :
    Sub 整理年度本益比資料()
    Dim newRow%, codeRow%, codeCol%, xR%, targetCode$
    
        codeRow = Sheets("年度本益比").[A65536].End(xlUp).Row ' 基準股票代號
        codeCol = Sheets("年度本益比").[A1].End(xlToRight).Column + 1 ' 新資料行
        newRow = Sheets("歷史本益比整合").[A65536].End(xlUp).Row   ' 年度股票代號

        Sheets("年度本益比").Select
        Cells(1, codeCol) = Left(hisDate, 4) & "/" & Mid(hisDate, 5, 2)  ' 製作年度表頭( 例 : 2007/12 )
        For xR = 2 To codeRow
            targetCode = Sheets("年度本益比").Range("A" & xR)
            Set xFind = Sheets("歷史本益比整合").Range("A2:A" & newRow).Find(targetCode, LookIn:=xlValues)
            If xFind Is Nothing Then
                Cells(xR, codeCol) = 0  ' 未尋獲 : 給予 0 值。
            Else
                xValue = Sheets("歷史本益比整合").Range("C" & xFind.Row)
                If xValue = "-" Or xValue = "N/A" Then
                    Cells(xR, codeCol) = 0
                Else
                    Cells(xR, codeCol) = Sheets("歷史本益比整合").Range("C" & xFind.Row)
                End If
            End If
        Next
        Set xFind = Nothing
    End Sub

[ 語法說明 ] :
Dim newRow%, codeRow%, codeCol%, xR%, targetCode$ : 宣告變數格式,% 是整數(Integer)簡寫 / $ 是文字(String)簡寫。
codeRow = Sheets(“年度本益比”).[A65536].End(xlUp).Row : 取得基準股票代號的資料列數(Row)。
codeCol = Sheets(“年度本益比”).[A1].End(xlToRight).Column + 1 : 取得資料行數(Column)。 +1 : 則是空白新行,將放置年度本益比資料。
Cells(1, codeCol) = Left(hisDate, 4) & “/” & Mid(hisDate, 5, 2) : 在(第1列/空白行) 放置年度資料( 例 : 2007/12 )。
For xR = 2 To codeRow : 利用 For ~ Next 迴圈,將基準的股票代號資料,執行一遍。
targetCode = Sheets(“年度本益比”).Range(“A” & xR) : 設定 targetCode 變數 — 從 A2 ~ A欄最後一列(codeRow)。
Set xFind = Sheets(“歷史本益比整合”).Range(“A2:A” & newRow).Find(targetCode, LookIn:=xlValues) : 利用 Set 陳述式 — 設定 xFind 物件變數Find(targetCode, LookIn:=xlValues) 是用以尋找 targetCode 代表的變數值,若尋獲 : 回傳 股票代碼;未尋獲 : 傳回 Nothing
If xFind Is Nothing Then : 運用 IF … is Nothing 判斷式來判別 xFind 物件變數內是否為 Nothing
Ture : 未尋獲 : Cells(xR, codeCol) = 0,給予 0 值。
False : 尋獲 : xValue = Sheets(“歷史本益比整合”).Range(“C” & xFind.Row) : 運用 xFind.Row 得知xFind物件變數的列號,進而取得歷史本益比資料。

[ 注意 ] :
※ 歷史本益比內的資料,因有 ” ” 及 ” N/A ” 值,這會對未來的計算造成影響,故必須將其處理(給予 0 值)。
If xValue = “-” Or xValue = “N/A” Then : 利用 If 判斷式來判別歷史本益比變數(xValue)內的數值,是否為 : ” ” 及 ” N/A ” 值。
Ture : 是 : Cells(xR, codeCol) = 0,給予 0 值。
False : 否 : Cells(xR, codeCol) = Sheets(“歷史本益比整合”).Range(“C” & xFind.Row),給予歷史本益比資料。
Set xFind = Nothing : 運用 Set 設定物件變數,會佔用系統空間,不再使用時,將其清除,才不會造成系統資源的浪費。

完整程式碼

    
    [ 程式碼 / 爬取年度本益比資料 ] :
    Dim hisDate$  ' 設定為 : 層級變數。
    Sub 爬取年度本益比資料()
    Dim xYear As Integer
        For xYear = 2007 To 2022
            hisDate = Trim(Str(xYear) & "1231")  ' 利用 Trim 刪除字串前後空白 !
            Sheets("歷史本益比整合").[C2:Z3000].ClearContents
            Call 爬取個股本益比資料
            Call 整理年度本益比資料
            Application.Wait (Now + TimeValue("00:00:05"))  ' 暫停5秒
        Next
    End Sub

    ' ------ < 上市公司 > ---------------------------------------------------------------------
    Sub 爬取個股本益比資料()
        Sheets("歷史TSE本益比").Select
        Cells.ClearContents
        With ActiveSheet.QueryTables.Add(Connection:= _
            "URL;https://www.twse.com.tw/rwd/zh/afterTrading/BWIBBU_d?date=" & hisDate & "&selectType=ALL&response=html" _
            , Destination:=Range("$A$1"))
    '        .CommandType = 0
    '        .Name = "BWIBBU_d?date=20230810&selectType=ALL&response=html"
            .FieldNames = True
            .RowNumbers = False
            .FillAdjacentFormulas = False
            .PreserveFormatting = True
            .RefreshOnFileOpen = False
            .BackgroundQuery = True
            .RefreshStyle = xlInsertDeleteCells
            .SavePassword = False
            .SaveData = True
            .AdjustColumnWidth = True
            .RefreshPeriod = 0
            .WebSelectionType = xlAllTables
            .WebFormatting = xlWebFormattingNone
            .WebPreFormattedTextToColumns = True
            .WebConsecutiveDelimitersAsOne = True
            .WebSingleBlockTextImport = False
            .WebDisableDateRecognition = False
            .WebDisableRedirections = False
            .Refresh BackgroundQuery:=False
            .Delete
        End With
        If [A1] = "" Then
                hisDate = Trim(Str(Int(hisDate) - 1))
                Call 爬取個股本益比資料
                Exit Sub
        End If     
        If [C2] = "本益比" Then
            Range("A2:C1000").Copy
            Sheets("歷史本益比整合").[A1].PasteSpecial Paste:=xlPasteAll
        Else
            Range("A2:E1000").Copy
            Sheets("歷史本益比整合").[A1].PasteSpecial Paste:=xlPasteAll
            Sheets("歷史本益比整合").Columns("C:D").Delete
        End If

        ' ------ < 上櫃公司 > --------------------------------------------------------------
        ' 複製上櫃股票歷史本益比資料
        chineseDate = Int(Left(hisDate, 4) - 1911) & "/" & Mid(hisDate, 5, 2) & "/" & Right(hisDate, 2)
        Sheets("歷史OTC本益比").Select
        Cells.ClearContents      
        With ActiveSheet.QueryTables.Add(Connection:= _
            "URL;https://www.tpex.org.tw/web/stock/aftertrading/peratio_analysis/pera_result.php?l=zh-tw&o=htm&d=" & chineseDate & "&c=&s=0,asc" _
            , Destination:=Range("$A$1"))
    '        .CommandType = 0
    '        .Name = "BWIBBU_d?date=20230810&selectType=ALL&response=html"
            .FieldNames = True
            .RowNumbers = False
            .FillAdjacentFormulas = False
            .PreserveFormatting = True
            .RefreshOnFileOpen = False
            .BackgroundQuery = True
            .RefreshStyle = xlInsertDeleteCells
            .SavePassword = False
            .SaveData = True
            .AdjustColumnWidth = True
            .RefreshPeriod = 0
            .WebSelectionType = xlAllTables
            .WebFormatting = xlWebFormattingNone
            .WebPreFormattedTextToColumns = True
            .WebConsecutiveDelimitersAsOne = True
            .WebSingleBlockTextImport = False
            .WebDisableDateRecognition = False
            .WebDisableRedirections = False
            .Refresh BackgroundQuery:=False
            .Delete
        End With       
        Range("A3:C1000").Copy
        newRow = Sheets("歷史本益比整合").[A1].End(xlDown).Row + 1
        Sheets("歷史本益比整合").Range("A" & newRow).PasteSpecial Paste:=xlPasteAll
        lastRow = Sheets("歷史本益比整合").[A1].End(xlDown).Row
        Sheets("歷史本益比整合").Rows(lastRow).Delete  ' 刪除 "共872筆" 文字資料
End Sub

     ' --------------------------------------------------------------------------------------
    Sub 整理年度本益比資料()
    Dim newRow%, codeRow%, codeCol%, xR%, targetCode$
        newRow = Sheets("歷史本益比整合").[A1].End(xlDown).Row   ' 年度股票代號
        codeRow = Sheets("年度本益比").[A65536].End(xlUp).Row ' 基準股票代號
        codeCol = Sheets("年度本益比").[A1].End(xlToRight).Column + 1 ' 新資料行
        Sheets("年度本益比").Select
        Cells(1, codeCol) = Left(hisDate, 4) & "/" & Mid(hisDate, 5, 2)
        For xR = 2 To codeRow
            targetCode = Sheets("年度本益比").Range("A" & xR)
            Set xFind = Sheets("歷史本益比整合").Range("A2:A" & newRow).Find(targetCode, LookIn:=xlValues)
                If xFind Is Nothing Then
                    Cells(xR, codeCol) = 0
                Else
                    xValue = Sheets("歷史本益比整合").Range("C" & xFind.Row)
                    If xValue = "-" Or xValue = "N/A" Then
                        Cells(xR, codeCol) = 0
                    Else
                        Cells(xR, codeCol) = Sheets("歷史本益比整合").Range("C" & xFind.Row)
                    End If
                End If
        Next
        Set xFind = Nothing
    End Sub

完成圖上市櫃公司16年歷史本益比資料

[ 完成圖 / 上市櫃公司16年歷史本益比資料 ] :
歷史本益比

結論

※「 歷史本益比 」是透過分析一家公司過去一段時間的本益比趨勢,讓投資人從中了解一家公司的投資價值和市場評價。文中,藉由VBA的腳本設計,一鍵執行 / 自動將上市櫃所有股票近16年的本益比資料,全部抓進EXCEL,有利於投資人洞察所有個股的本益比趨勢。

相 關 文 章

[ 1 ] : 自動上網爬取「 本益比 」 — 找出被低估的股票
※「 本益比 」是股票投資中經常使用的一種重要指標,可以幫助投資者初步評估公司的投資價值。本文透過VBA的腳本設計,每日自動爬取上市櫃股票最新的本益比數據,並利用排序的方式,將其本益比資料由小到大排序,有利於查找目前最有可能被低估的股票資料。

[ 2 ] : 自動爬取上市櫃股票近16年「 歷史本益比 」
※ 「 歷史本益比 」是透過分析一家公司過去一段時間的本益比趨勢,讓投資人從中了解一家公司的投資價值和市場評價。文中,藉由VBA的腳本設計,一鍵執行 / 自動將上市櫃所有股票近16年的本益比資料,全部抓進EXCEL,有利於投資人洞察所有個股的本益比趨勢。

[ 3 ] :「 本益比多少合理 ? 」史上最佛心的VBA教學 — 算出 合理本益比
※「 合理本益比 」是指一家公司的股票在特定時刻或特定市場環境下,被認為是合理價值的價益比率。文中,藉由VBA程序計算歷史本益比均值 / 運用QueryTable工具爬取個股EPS / 借助DDE語法抓取個股即時數據,求得個股合理價位,最後再以黃金切割率來定義便宜價與昂貴價,完成上市櫃所有股票的數據設定。

V B A 資 源

EXCEL & VBA功能 – 綜合筆記
※ EXCEL & VBA功能 筆記 : 將針對文章中所使用的 EXCEL 及 VBA公式 / 工具操作 / 巨集設定 / 控制項的運用,做個整合記錄,方便大家在學習當下的參考與使用。

VBA指令 – 彙整筆記
※ VBA 提供相當多的指令用法,VBA指令 彙整筆記,將會陸續記錄 VBA文章 中,所用過的 VBA指令,方便學員們對照運用。

VBA程式語法 – 彙整筆記
※ 語法就是程式的文法。 使用者要與電腦溝通,就必須遵守這些規則。VBA程式語法 筆記 : 將針對 VBA文章 中所使用的 VBA程式語法,做個整合記錄,方便大家在學習當下參考與使用。