AnhNQT
Thành viên chính thức
- Tham gia
- 6/11/18
- Bài viết
- 61
- Được thích
- 5
- Giới tính
- Nam
Khi e import dữ liệu từ web. Tại PQ sẽ view các table, lúc đó tích chọn để load về. Khi load về được rồi thì kiểu gì cũng có thể xử lý được dữ liệu.Không phải dữ liệu nguồn từ một database hay file Excel mà là nguồn từ URL em nhé.
Nếu url trả về Table thì đơn giản, nếu trả về html không vẫn conver thành bảng được, mấy cái web có sử dụng token dùng power query vẫn xử lý được vì nó cho phép nhập header, power query trên BI thì xịn xò hơn nó tự conver json và htlm thành bảng luônLý ra bạn nên viết rõ là:
Kết quả lấy dữ liệu từ web về là một Table chuẩn chỉ, vậy nên muốn làm gì cũng được.
Chưa kể nó cho phép lưu data ngoài bảng tính hay trên Ram, lưu trên Ram thì data cho thể cả trăm triệu dòng, dùng power pivot nâng cao trả kết quả động (power pivot và power Bi nó sử dụng cùng công nghệ với mấy thằng SAP đời mới bây giờ), từ cái kết quả động đó có thể tạo hơn 100 cái report khác nhau với tốc độ vài s, nếu ví VBA là ngôn ngữ bậc thấp thì M code là ngôn ngữ bậc cao , có thể tốc độ một số trường hợp không bằng VBA nhưng về query connect, ETL, tính toán, report, visualize ... thì VBA không so được, nó là anh em với power BI nhưng nó miễn phí, có thể nói power query+power pivot trong excel là tool BI miễn phí tốt nhất, cái connect của power query hiện nay chắc hơn 140 source rồi như file, Oracle, Sql, mySQL, postgresql, odbc, cloud, web...chỉ riêng việc connect SQL trong power query với ADO trong vba cũng có khác biệt rồi, ADO chỉ connect các câu query select, còn trong power query cho phép code thuần như tạo bảng tạm, loop rồi lấy kết quả sau cùng thôiJoin hiểu theo SQL là tạo relation và join, trong Power query gọi là merge và có thể merge nhiều table với nhau miễn là có trường Key (nguồn từ web hay bất kỳ đâu cũng được).
Groupby thì Power query làm được từ bất kỳ nguồn nào, cứ lấy về rồi thêm step groupby
Các tính năng tôi kể ở trên cũng vậy, hễ lấy được về rồi là làm được hết
Nói thêm: Nếu trang web có nhiều page(s), mỗi page là 1 table theo ngày (hoặc theo bất kỳ tiêu chí nào), có thể dùng vòng lặp ngay trong hàm M để lấy về và union (combine) lại với nhau
Option Explicit
'Kien thuc code trong file nay ban xem link: https://www.youtube.com/watch?v=OSfcpLGVLOk
Sub LayTyGia()
Range("J6:L6").Value = "Waiting..."
Range("J6:L6").Value = LayTyGiaTheoNgay(Range("J2").Value, Range("J3").Value)
End Sub
Function LayTyGiaTheoNgay(dNgay As Date, strNgoaiTe As String)
Dim qry As QueryTable, rng As Range, I As Long, arrRes(1 To 3)
LayTableTuWeb dNgay
Set qry = ThisWorkbook.Sheets("webdata").QueryTables(1)
Set rng = qry.ResultRange
For I = 3 To rng.Rows.Count
If StrComp(rng.Rows(I).Cells(, 2).Value, strNgoaiTe, vbTextCompare) = 0 Then
arrRes(1) = rng.Rows(I).Cells(, 3).Value
arrRes(2) = rng.Rows(I).Cells(, 4).Value
arrRes(3) = rng.Rows(I).Cells(, 5).Value
Exit For
End If
Next
LayTyGiaTheoNgay = arrRes
End Function
Sub LayTableTuWeb(ByVal dNgay As Date)
Dim qry As QueryTable
Dim sh As Worksheet
Dim CnnStr As String
Set sh = ThisWorkbook.Sheets("webdata")
'Xoa querytable truoc do
XoaQT sh
CnnStr = "URL;https://portal.vietcombank.com.vn/UserControls/TVPortal.TyGia/pListTyGia.aspx?txttungay=" & Format(dNgay, "dd/mm/yyyy")
Set qry = sh.QueryTables.Add(CnnStr, sh.Range("A1"))
'Query
qry.WebSelectionType = xlSpecifiedTables
qry.WebFormatting = xlWebFormattingNone
qry.WebTables = """ctl00_Content_ExrateView""" 'hoan nhieu hon mot table
qry.Refresh False 'Load du lieu
End Sub
Sub XoaQT(sh As Worksheet)
Dim qry As QueryTable
On Error Resume Next 'Bo qua loi
For Each qry In sh.QueryTables
qry.ResultRange.ClearContents 'Xoa data trong vung table
qry.Delete 'Xoa QueryTable
Next
End Sub
Đúng là 1 bài toán có nhiều cách giải. Quan trọng người dùng cảm thấy happy với phương án nào.Đúng như tôi xem qua câu hỏi ban đầu. Để đơn giản bạn dùng phương pháp QueryTable mà tôi đã gửi link youtube hướng dẫn. Dùng nguyên kiến thức đó, kết hợp với code thêm về vòng lặp để so sánh là ra. File đính kém là toàn bộ mã nguồn.
Mã nguồn:
Mã:Option Explicit 'Kien thuc code trong file nay ban xem link: https://www.youtube.com/watch?v=OSfcpLGVLOk Sub LayTyGia() Range("J6:L6").Value = "Waiting..." Range("J6:L6").Value = LayTyGiaTheoNgay(Range("J2").Value, Range("J3").Value) End Sub Function LayTyGiaTheoNgay(dNgay As Date, strNgoaiTe As String) Dim qry As QueryTable, rng As Range, I As Long, arrRes(1 To 3) LayTableTuWeb dNgay Set qry = ThisWorkbook.Sheets("webdata").QueryTables(1) Set rng = qry.ResultRange For I = 3 To rng.Rows.Count If StrComp(rng.Rows(I).Cells(, 2).Value, strNgoaiTe, vbTextCompare) = 0 Then arrRes(1) = rng.Rows(I).Cells(, 3).Value arrRes(2) = rng.Rows(I).Cells(, 4).Value arrRes(3) = rng.Rows(I).Cells(, 5).Value Exit For End If Next LayTyGiaTheoNgay = arrRes End Function Sub LayTableTuWeb(ByVal dNgay As Date) Dim qry As QueryTable Dim sh As Worksheet Dim CnnStr As String Set sh = ThisWorkbook.Sheets("webdata") 'Xoa querytable truoc do XoaQT sh CnnStr = "URL;https://portal.vietcombank.com.vn/UserControls/TVPortal.TyGia/pListTyGia.aspx?txttungay=" & Format(dNgay, "dd/mm/yyyy") Set qry = sh.QueryTables.Add(CnnStr, sh.Range("A1")) 'Query qry.WebSelectionType = xlSpecifiedTables qry.WebFormatting = xlWebFormattingNone qry.WebTables = """ctl00_Content_ExrateView""" 'hoan nhieu hon mot table qry.Refresh False 'Load du lieu End Sub Sub XoaQT(sh As Worksheet) Dim qry As QueryTable On Error Resume Next 'Bo qua loi For Each qry In sh.QueryTables qry.ResultRange.ClearContents 'Xoa data trong vung table qry.Delete 'Xoa QueryTable Next End Sub
Mình cũng có nêu ở bài #33 rồi đó.Nếu url trả về Table thì đơn giản, nếu trả về html không vẫn conver thành bảng được, mấy cái web có sử dụng token dùng power query vẫn xử lý được vì nó cho phép nhập header, power query trên BI thì xịn xò hơn nó tự conver json và htlm thành bảng luôn
Nếu có điều kiện, mong anh chia sẻ những cái siêu hịn này ở 1 Topic mới, để anh/em GPE học hỏi.Cái query from web chỉ đơn giản là lấy dữ liệu từ một url về, và chỉ thế mà thôi. Mỗi lần thực hiện là phải tạo ra một query mới.
Chẳng có lý do gì để so sánh nó với Power Query cả, bởi nó chỉ là 1 chức năng.
Còn Power Query là một bộ công cụ/ thư viện hoàn chỉnh được tích hợp vào Excel, nó có môi trường viết mã lệnh (M code), cho phép thực hiện mã lệnh (tương tự như môi trường VBA).
Ngay cái phần web scraping có hẳn thư viện Web siêu hịn.
Chưa kể kết hợp với Html.Table, Json cho phép xử lý dữ liệu trả về ngon lành cành đào.
View attachment 264062
Một đoạn code mình thấy trên diễn đàn từ năm 2015 vẫn còn chạy được.Xin chào các Bác GPE,
Em cần giúp để lấy tỷ giá VCB về excel theo một vài mã cần và theo ngày ạ. Nếu được thì ngày nào cũng tự lấy về thì càng tốt ạ.
Em cảm ơn!
Quan trọng là trên web nó không có option để chọn từ ngày đến ngày. Chứ a nghĩ là lấy được @hoangminhtienBây giờ làm cách nào để có 1 bảng với tất cả các tỷ giá trong 1 khoảng thời gian (ví dụ của tháng 7 từ 1-7-2021 đến 31-7-2021) mà không phải nhập từng ngày một vào B4 các bác nhỉ? Em nghĩ tới vòng lặp FOR nhưng mà không biết cách làm. Nhờ các thầy/ các tiền bối hướng dẫn
1. Viết 1 hàm UnionQuery: Union 2 query truyền vào (Query1, Query2)Bây giờ làm cách nào để có 1 bảng với tất cả các tỷ giá trong 1 khoảng thời gian (ví dụ của tháng 7 từ 1-7-2021 đến 31-7-2021) mà không phải nhập từng ngày một vào B4 các bác nhỉ? Em nghĩ tới vòng lặp FOR nhưng mà không biết cách làm. Nhờ các thầy/ các tiền bối hướng dẫn
Dùng cách cơ bản thôi cũng đượcQuan trọng là trên web nó không có option để chọn từ ngày đến ngày. Chứ a nghĩ là lấy được @hoangminhtien
Sub Query1()
Dim qry As QueryTable, StartDate As Date, EndDate As Date
Dim CnnStr As String, iDate As Date, sh As Worksheet
Dim NextRw As Long, NewLastRw As Long
Set sh = Sheet2
For I = sh.QueryTables.Count To 1 Step -1
sh.QueryTables(I).Delete
Next
StartDate = sh.[B2]: EndDate = sh.[D2]
Application.DisplayAlerts = False
Application.ScreenUpdating = False
sh.Range("A4:F10000").ClearContents
For iDate = StartDate To EndDate
CnnStr = "URL;https://portal.vietcombank.com.vn/UserControls/TVPortal.TyGia/pListTyGia.aspx?txttungay=" & _
Format(iDate, "dd/mm/yyyy")
NextRw = sh.Range("B10000").End(xlUp).Row + 1
Set qry = sh.QueryTables.Add(CnnStr, sh.Cells(NextRw, 2))
With qry
.WebSelectionType = xlSpecifiedTables
.WebTables = """ctl00_Content_ExrateView"""
.Refresh False
.Refresh BackgroundQuery:=False
.SaveData = True
End With
NewLastRw = sh.Range("B10000").End(xlUp).Row
sh.Range(Cells(NextRw, 1), Cells(NewLastRw, 1)).Value = iDate
Next
Application.DisplayAlerts = True
sh.Range("A3:F" & NewLastRw).AutoFilter Field:=4, Criteria1:="=Mua", _
Operator:=xlOr, Criteria2:="=Ti" & ChrW(7873) & "n m" & ChrW(7863) & "t"
Rows("4:" & NewLastRw).Delete Shift:=xlUp
sh.ShowAllData
Application.ScreenUpdating = True
Set qry = Nothing
Set sh = Nothing
End Sub
let
WebAddress = Excel.CurrentWorkbook(){[Name="WebAdd"]}[Content]{0}[Column1] ,
DateFrom = Number.From(Excel.CurrentWorkbook(){[Name="DFrom"]}[Content]{0}[Column1]) ,
DateTo = Number.From(Excel.CurrentWorkbook(){[Name="DTo"]}[Content]{0}[Column1]) ,
DaysNo = {0..DateTo - DateFrom},
abc=Date.ToText(Date.From(DaysNo{0}+DateFrom),"dd/MM/yyyy"),
DataW = List.Transform(DaysNo, (wd) =>
let
Datewd=DaysNo{wd}+DateFrom,
Source = Web.Page(Web.Contents(WebAddress & Date.ToText(Date.From(Datewd),"dd/MM/yyyy"))),
Data0 = Source{0}[Data],
RenamedColumns = Table.RenameColumns(Data0,{{"Ngoại tệ Tên ngoại tệ", "Tên Ngoại tệ"}, {"Ngoại tệ Mã NT", "Mã ngoại tệ"}}),
RemoveRows = Table.Skip(RenamedColumns,2),
ReplaceValue = Table.ReplaceValue(RemoveRows,"-","0",Replacer.ReplaceText,{"Mua Tiền mặt"}),
ChangeType = Table.TransformColumnTypes(ReplaceValue,{{"Mua Tiền mặt", type number}, {"Mua Chuyển khoản", type number},
{"Bán", type number}}),
AddDate = Table.AddColumn(ChangeType, "Date", each Date.From(Datewd), Date.Type)
in AddDate),
List2 =Table.FromList(DataW,Splitter.SplitByNothing()),
ListColumns2 = Table.ColumnNames(DataW{0}),
KetQua = Table.ReorderColumns(Table.ExpandTableColumn(List2, "Column1", ListColumns2),
{"Date", "Tên Ngoại tệ", "Mã ngoại tệ", "Mua Tiền mặt", "Mua Chuyển khoản", "Bán"})
in
KetQua
Power Query đúng là công lực thượng thừa.Cách khác: Dùng vòng lặp trong Power Query
PHP:let WebAddress = Excel.CurrentWorkbook(){[Name="WebAdd"]}[Content]{0}[Column1] , DateFrom = Number.From(Excel.CurrentWorkbook(){[Name="DFrom"]}[Content]{0}[Column1]) , DateTo = Number.From(Excel.CurrentWorkbook(){[Name="DTo"]}[Content]{0}[Column1]) , DaysNo = {0..DateTo - DateFrom}, abc=Date.ToText(Date.From(DaysNo{0}+DateFrom),"dd/MM/yyyy"), DataW = List.Transform(DaysNo, (wd) => let Datewd=DaysNo{wd}+DateFrom, Source = Web.Page(Web.Contents(WebAddress & Date.ToText(Date.From(Datewd),"dd/MM/yyyy"))), Data0 = Source{0}[Data], RenamedColumns = Table.RenameColumns(Data0,{{"Ngoại tệ Tên ngoại tệ", "Tên Ngoại tệ"}, {"Ngoại tệ Mã NT", "Mã ngoại tệ"}}), RemoveRows = Table.Skip(RenamedColumns,2), ReplaceValue = Table.ReplaceValue(RemoveRows,"-","0",Replacer.ReplaceText,{"Mua Tiền mặt"}), ChangeType = Table.TransformColumnTypes(ReplaceValue,{{"Mua Tiền mặt", type number}, {"Mua Chuyển khoản", type number}, {"Bán", type number}}), AddDate = Table.AddColumn(ChangeType, "Date", each Date.From(Datewd), Date.Type) in AddDate), List2 =Table.FromList(DataW,Splitter.SplitByNothing()), ListColumns2 = Table.ColumnNames(DataW{0}), KetQua = Table.ReorderColumns(Table.ExpandTableColumn(List2, "Column1", ListColumns2), {"Date", "Tên Ngoại tệ", "Mã ngoại tệ", "Mua Tiền mặt", "Mua Chuyển khoản", "Bán"}) in KetQua
Chọn từ ngày đến ngày và refresh
View attachment 264396
Bác @ptm0412 ơi, em dùng được 1 thời gian đến hôm này bị lỗi này ạ, Bác sửa giúp em với được không?Cách khác: Dùng vòng lặp trong Power Query
PHP:let WebAddress = Excel.CurrentWorkbook(){[Name="WebAdd"]}[Content]{0}[Column1] , DateFrom = Number.From(Excel.CurrentWorkbook(){[Name="DFrom"]}[Content]{0}[Column1]) , DateTo = Number.From(Excel.CurrentWorkbook(){[Name="DTo"]}[Content]{0}[Column1]) , DaysNo = {0..DateTo - DateFrom}, abc=Date.ToText(Date.From(DaysNo{0}+DateFrom),"dd/MM/yyyy"), DataW = List.Transform(DaysNo, (wd) => let Datewd=DaysNo{wd}+DateFrom, Source = Web.Page(Web.Contents(WebAddress & Date.ToText(Date.From(Datewd),"dd/MM/yyyy"))), Data0 = Source{0}[Data], RenamedColumns = Table.RenameColumns(Data0,{{"Ngoại tệ Tên ngoại tệ", "Tên Ngoại tệ"}, {"Ngoại tệ Mã NT", "Mã ngoại tệ"}}), RemoveRows = Table.Skip(RenamedColumns,2), ReplaceValue = Table.ReplaceValue(RemoveRows,"-","0",Replacer.ReplaceText,{"Mua Tiền mặt"}), ChangeType = Table.TransformColumnTypes(ReplaceValue,{{"Mua Tiền mặt", type number}, {"Mua Chuyển khoản", type number}, {"Bán", type number}}), AddDate = Table.AddColumn(ChangeType, "Date", each Date.From(Datewd), Date.Type) in AddDate), List2 =Table.FromList(DataW,Splitter.SplitByNothing()), ListColumns2 = Table.ColumnNames(DataW{0}), KetQua = Table.ReorderColumns(Table.ExpandTableColumn(List2, "Column1", ListColumns2), {"Date", "Tên Ngoại tệ", "Mã ngoại tệ", "Mua Tiền mặt", "Mua Chuyển khoản", "Bán"}) in KetQua
Chọn từ ngày đến ngày và refresh
View attachment 264396
Tôi refresh thấy vẫn chạy bình thường, bạn refresh vài lần xem sao, hoặc đổi mốc thời gian lấy.Bác @ptm0412 ơi, em dùng được 1 thời gian đến hôm này bị lỗi này ạ, Bác sửa giúp em với được không?
View attachment 266169
uhm, lấy mốc như thế thì căng quá, dữ liệu của nhà băng họ nhiều, chắc cùng lắm 6 tháng phải backup rồi.vâng, chắc tại để ngày dài quá, em để từ 1/2020 - hiện tại
Bác có lấy được tỷ giá của ngân hàng MB với BIDV không? Em làm theo bác mà không được. Em cảm ơn!Mở trang VCB -> vô mục Tỷ Giá -> click phải chuột chọn "Inspect" và chọn các mục như hình sẽ thấy câu lệnh request.
View attachment 264026