Import chuỗi JSON vào Excel

Liên hệ QC
Trước tiên ta cần hiểu sơ qua chuỗi JSON là gì nhé!
Thông thường lập trình web người ta sẽ liên kết dữ liệu vào một hệ quản trị cơ sở dữ liệu. Hệ quản trị này phải được cài đặt trước (MySQL chẳng hạn)
Với những CSDL dạng nhỏ, để tránh phiền phức về việc cài đặt chương trình, người ta muốn "ăn ngay" bằng cách chuyển đổi CSDL thành dạng chuỗi theo cấu trúc nào đó. Khi download về máy tính, ta lại giải mã cấu trúc chuỗi này để nhận được dữ liệu hoàn chỉnh
Chuỗi JSON chính là cái chuỗi có cấu trúc đặt biệt như tôi nói ở trên. Thêm nữa là hiện nay JSON hỗ trợ hầu hết các ngôn ngữ lập trình (vì thực chất cấu trúc này chỉ là dạng chuỗi)
----------------------------------
Tôi giả định rằng ông lập trình viên web giao cho tôi đường link như sau:
http://warehouse.bigapptech.com.vn/api/material/get
Ông ấy nói rằng đường link này sẽ trả về một chuỗi JSON. Tôi gõ link trên vào trình duyệt và nhận được kết quả

Capture1.JPG

hoặc:

Capture2.JPG


tùy theo cách hiển thị của trình duyệt (Firefox cho phép hiển thị theo 2 kiểu)
-------------------
Giờ tôi sẽ tiến hành viết code để 1> Download chuỗi JSON, 2> Biến đổi chuỗi JSON thành dữ liệu trên Excel

Mã:
Public Const URL = "http://warehouse.bigapptech.com.vn/api/material/get"
Dim data, total
Function DownloadJSON(ByVal sURL As String) As Object
  Dim objHTTP   As Object
  Dim objScript As Object
  Set objScript = CreateObject("MSScriptControl.ScriptControl")
  objScript.Language = "JScript"
  Set objHTTP = CreateObject("MSXML2.XMLHTTP")
  On Error Resume Next
  With objHTTP
    .Open "GET", sURL, False
    .send
    Set DownloadJSON = objScript.Eval("(" & .responseText & ")")
    .abort
  End With
  Set objHTTP = Nothing: Set objScript = Nothing
End Function
Function GetBigAppTech(ByVal JSON As Object)
  Dim jsData    As Object
  Dim jsItem    As Object
  Dim lCount    As Long
  Dim idx       As Long
  On Error Resume Next
  If JSON Is Nothing Then Exit Function
  Set jsData = JSON.data
  lCount = JSON.total
  ReDim aRes(1 To lCount, 1 To 3)
  For Each jsItem In jsData
    idx = idx + 1
    aRes(idx, 1) = jsItem.material_id
    aRes(idx, 2) = jsItem.material_name
    aRes(idx, 3) = jsItem.material_inventory
  Next
  If idx Then GetBigAppTech = aRes
  Set jsData = Nothing: Set jsItem = Nothing
End Function
Sub Test()
  Dim aRes, JSON As Object
  Set JSON = DownloadJSON(URL)
  If JSON Is Nothing Then
    MsgBox "Please check the status of Network!"
    Exit Sub
  End If
  aRes = GetBigAppTech(JSON)
  If IsArray(aRes) Then
    Range("A1:C1").Resize(UBound(aRes)).Value = aRes
    MsgBox "Done!"
  End If
End Sub

Code chạy tốt nhưng có 3 vấn đề xuất hiện:
1> Các bạn để ý câu lệnh Set jsData = JSON.data, ngay khi gõ xong thì chắc chắn chữ data sẽ bị biến thành Data (viết HOA ký tự "D"). Ác cái code này có phân biệt HOA thường nên sẽ bị lỗi (dòng thứ 2 trong kết quả trên trình duyệt là data chứ không phải Data). Tôi đang chơi "ăn gian" bằng cách khai báo biến data trên đầu code (mà chẳng để làm gì)
2> Cũng câu lệnh trên Set jsData = JSON.data, ý tôi là muốn lấy dữ liệu từ nhánh data. Trong trường hợp tôi muốn viết code theo cách tổng quát hơn:
Mã:
Function GetBigAppTech(ByVal JSON As Object, byVal sProperty as String)
....................
End Function
thì cái đối số sProperty trong hàm sẽ được truyền như thế nào cho câu lệnh trên (ở đây tôi muốn truyền sProperty = "data")
3> Tôi có câu lệnh:
Mã:
 lCount = JSON.total
  ReDim aRes(1 To lCount, 1 To 3)
là vì may mắn chuỗi JSON trả về có đoạn total: 5 nên từ đây tôi biết được dữ liệu có 5 dòng. Đặt trường hợp chuỗi JSON này không có dòng total: 5 như trên thì bằng cách nào tôi biết được phải khai báo chiều thứ nhất cho mảng aRes bao nhiêu là đủ?
--------------------------
Đang tập tành nên còn nhiều thứ chưa biết nên nhận được sự góp ý từ các bạn. Xin cảm ơn
(thật ra trên mạng có cả 1 thư việc viết sẵn để xử lý nhưng dài quá, trong khi tôi muốn tự mình xây dựng lấy ứng dụng)
 

File đính kèm

  • GetJSData.xlsm
    47.9 KB · Đọc: 89
em chào các anh, chị
trong link json em thấy có link người ta convert ngày tháng sang 1 dãy số

hình 1: ngày tháng bình thường

1675900364938.png

hình 2: ngày tháng đã được convert trong kết quả của link json trả về

1675900420862.png

ví dụ làm sao mình biết được dãy số 1677171600 là ngày 02/03/2023 anh chị nhỉ ?

em cám ơn tất cả các anh chị ạ.
 
em chào các anh, chị
trong link json em thấy có link người ta convert ngày tháng sang 1 dãy số

hình 1: ngày tháng bình thường

View attachment 286238

hình 2: ngày tháng đã được convert trong kết quả của link json trả về

View attachment 286239

ví dụ làm sao mình biết được dãy số 1677171600 là ngày 02/03/2023 anh chị nhỉ ?

em cám ơn tất cả các anh chị ạ.
PHP:
Function UnixTimestampToDate(Timestamp As Double) As Date
    UnixTimestampToDate = DateAdd("s", Timestamp, #1/1/1970#)
End Function
Không chắc là can thiệp được ngay khi tách dữ liệu, nên nếu chưa có giải pháp nào thì bạn xem thử, cho function bên trên vào trước kế quả trả về (xem ví dụ bên dưới).
PHP:
                                 '
Sub Test()
    Dim UnixTimestamp As Double
    UnixTimestamp = 1677171600
    Debug.Print UnixTimestampToDate(UnixTimestamp)
End Sub
 
PHP:
Function UnixTimestampToDate(Timestamp As Double) As Date
    UnixTimestampToDate = DateAdd("s", Timestamp, #1/1/1970#)
End Function
Không chắc là can thiệp được ngay khi tách dữ liệu, nên nếu chưa có giải pháp nào thì bạn xem thử, cho function bên trên vào trước kế quả trả về (xem ví dụ bên dưới).
PHP:
                                 '
Sub Test()
    Dim UnixTimestamp As Double
    UnixTimestamp = 1677171600
    Debug.Print UnixTimestampToDate(UnixTimestamp)
End Sub
em chào bác @huhumalu

em kiểm tra thì thấy kết quả ra ngày 23/02/2023 là không đúng ạ.

ngày đúng là ngày 02/03/2023

em cám ơn bác

1675905712456.png
 
Cái này mình cũng thấy lạ, vì trông có vẻ là UNIX timestamp, nhưng khi chuyển đổi thử (vd: https://timestamp.online/) thì lại ra giá trị khác.
Bạn xem lại kết quả trả về có bị nhầm lẫn gì không.
dạ không có gì nhầm lẫn đâu ạ

em gửi link @nguyendang95 xem thử ạ

link json:


link web:


em xin cảm ơn @nguyendang95 , và @huhumalu nhiều ạ
 
dạ đó là kết quả trong link json trả về

Đó gì mà đó. Bạn nhầm xừ giá trị này với kết quả kia lại còn cố nói.

{"table":"dividend","id":33981,"title":"SAB: chia cổ tức bằng tiền, tỉ lệ 0.1 (1,000 đồng/CP)","published_date":1670346000,"symbol":"SAB","company_name":"Tổng Công ty Cổ phần Bia - Rượu - Nước giải khát Sài Gòn","floor":"HOSE","type":"cash","record_date":1677776400,"exright_date":1677690000,"payout_date":1679590800}

record_date (Ngày ĐKCC): 1677776400 ~ 03/03/2023 GMT+7
exright_date (Ngày GDKHQ): 1677690000 ~ 02/03/2023 GMT+7
payout_date (Ngày thực hiện): 1679590800 ~ 24/03/2023 GMT+7

1675912591710.png
 
Đó gì mà đó. Bạn nhầm xừ giá trị này với kết quả kia lại còn cố nói.

{"table":"dividend","id":33981,"title":"SAB: chia cổ tức bằng tiền, tỉ lệ 0.1 (1,000 đồng/CP)","published_date":1670346000,"symbol":"SAB","company_name":"Tổng Công ty Cổ phần Bia - Rượu - Nước giải khát Sài Gòn","floor":"HOSE","type":"cash","record_date":1677776400,"exright_date":1677690000,"payout_date":1679590800}

record_date (Ngày ĐKCC): 1677776400 ~ 03/03/2023 GMT+7
exright_date (Ngày GDKHQ): 1677690000 ~ 02/03/2023 GMT+7
payout_date (Ngày thực hiện): 1679590800 ~ 24/03/2023 GMT+7

View attachment 286242
dạ em nhầm ạ, xin đa tạ bác
 
PHP:
Function UnixTimestampToDate(Timestamp As Double) As Date
    UnixTimestampToDate = DateAdd("s", Timestamp, #1/1/1970#)
End Function
Không chắc là can thiệp được ngay khi tách dữ liệu, nên nếu chưa có giải pháp nào thì bạn xem thử, cho function bên trên vào trước kế quả trả về (xem ví dụ bên dưới).
PHP:
                                 '
Sub Test()
    Dim UnixTimestamp As Double
    UnixTimestamp = 1677171600
    Debug.Print UnixTimestampToDate(UnixTimestamp)
End Sub
cho em hỏi với bác @huhumalu
code bác là convert từ 1 dãy số sang ngày tháng

ngược lại muốn convert từ 1 ngày sang dãy số thì làm sao ạ ?

vì có link json thể hiện dạng dãy số trong link nên em gõ ngày trong 1 ô excel sau đó em sẽ convert sang dãy số ạ
em xin cảm ơn
 
Chuỗi số đó gọi là "Unix timestamp" bạn tìm trên google thêm. Chuỗi này là kết quả trả về theo giây, tính từ thời điểm đang xét trừ đi thời điểm "January 1, 1970, at 00:00:00 UTC".
Nên việc chuyển qua hay lại thì thuần túy trừ đi lượng "ngày" đã được đổi về "giây". Yếu tố ảnh hưởng ở đây là múi giờ. Bạn phải đổi ngày tháng và thời điểm đang xét về với múi giờ UTC --> sau thì trừ đi "January 1, 1970, 00:00:00 UTC".
Bạn nhập chuỗi ngày tháng nếu thiếu giờ sẽ được coi là 00:00:00 AM; và được hiểu là UTC.
Việt Nam mình ở múi UTC+7; vậy thời gian bạn phải trừ đi "7 tiếng đồng hồ"
Bạn tham khảo 2 hàm bên dưới và tìm hiểu thêm.

PHP:
Sub DateToUnixTimestamp()
    Dim dt As Date
    dt = #3/2/2023 5:00:00 PM#
    Debug.Print DateDiff("s", #1/1/1970#, dt)
End Sub
Sub UnixTimestampToDate()
    Dim UniTime As Double
    UniTime = 1677776400
    Debug.Print DateAdd("s", UniTime, #1/1/1970#)
End Sub
 
Chuỗi số đó gọi là "Unix timestamp" bạn tìm trên google thêm. Chuỗi này là kết quả trả về theo giây, tính từ thời điểm đang xét trừ đi thời điểm "January 1, 1970, at 00:00:00 UTC".
Nên việc chuyển qua hay lại thì thuần túy trừ đi lượng "ngày" đã được đổi về "giây". Yếu tố ảnh hưởng ở đây là múi giờ. Bạn phải đổi ngày tháng và thời điểm đang xét về với múi giờ UTC --> sau thì trừ đi "January 1, 1970, 00:00:00 UTC".
Bạn nhập chuỗi ngày tháng nếu thiếu giờ sẽ được coi là 00:00:00 AM; và được hiểu là UTC.
Việt Nam mình ở múi UTC+7; vậy thời gian bạn phải trừ đi "7 tiếng đồng hồ"
Bạn tham khảo 2 hàm bên dưới và tìm hiểu thêm.

PHP:
Sub DateToUnixTimestamp()
    Dim dt As Date
    dt = #3/2/2023 5:00:00 PM#
    Debug.Print DateDiff("s", #1/1/1970#, dt)
End Sub
Sub UnixTimestampToDate()
    Dim UniTime As Double
    UniTime = 1677776400
    Debug.Print DateAdd("s", UniTime, #1/1/1970#)
End Sub
dạ em cảm ơn bác @huhumalu
 
Web KT
Back
Top Bottom