thongkorn โพสต์ 2023-11-21 15:48:37

[VB.NET] การนำข้อมูลรหัสไปรษณีย์จากรูปแบบ JSON มาแสดงผลลงในตารางกริด และค้นหาข้อมูลได้

ก็เป็นอีกหนึ่งแหล่งที่มาของไฟล์ JSON ที่มีข้อมูลรหัสไปรษณีย์ทั่วประเทศไทย แต่รูปแบบ JSON ของผู้จัดทำเขาออกแนวกลับด้าน คือใช้รหัสไปรษณีย์ในการค้นหาชื่อตำบล อำเภอและจังหวัด แต่โดยปกติเราจะค้นหาด้วยชื่อตำบล อำเภอและจังหวัด เพื่อหารหัสไปรษณีย์มากกว่า พอนำ JSON ชุดนี้มาใช้งาน ก็เลยต้องเขียนโค้ดขึ้นมายากสักหน่อย ในการแยกเอาข้อมูลตำบล อำเภอ จังหวัดที่มันตรงกันเท่านั้น ด้วยการใช้งาน Lambda Expression ... อย่างไรก็ตามเราก็ใช้หลักการเดิม คือ การ Deserialize JSON แยกเอาข้อมูลมาเก็บไว้ใน DataTable ก่อน จากนั้นก็จะทำ BindingSource อีกที แล้วนำไปแสดงผลลงในตารางกริด ส่วนในการค้นหาก็จะใช้ Method Filter ...

แหล่งข้อมูลต้นฉบับไฟล์ JSON ...

http://www.g2gsoft.com/webboard/images/VBNet/jsonpostcode.png


http://www.g2gsoft.com/webboard/images/VBNet/Newtonsoft.png
Add Reference ... NewtonSoft

ตัวอย่างรูปแบบ JSON ...
{
    "zipCode": "10100",
    "subDistrictList": [
      {
      "subDistrictId": "100801",
      "districtId": "1008",
      "provinceId": "10",
      "subDistrictName": "ป้อมปราบ"
      },
      {
      "subDistrictId": "100802",
      "districtId": "1008",
      "provinceId": "10",
      "subDistrictName": "วัดเทพศิรินทร์"
      },
      {
      "subDistrictId": "100803",
      "districtId": "1008",
      "provinceId": "10",
      "subDistrictName": "คลองมหานาค"
      },
      {
      "subDistrictId": "100804",
      "districtId": "1008",
      "provinceId": "10",
      "subDistrictName": "บ้านบาตร"
      },
      {
      "subDistrictId": "100805",
      "districtId": "1008",
      "provinceId": "10",
      "subDistrictName": "วัดโสมนัส"
      },
      {
      "subDistrictId": "101301",
      "districtId": "1013",
      "provinceId": "10",
      "subDistrictName": "จักรวรรดิ"
      },
      {
      "subDistrictId": "101302",
      "districtId": "1013",
      "provinceId": "10",
      "subDistrictName": "สัมพันธวงศ์"
      },
      {
      "subDistrictId": "101303",
      "districtId": "1013",
      "provinceId": "10",
      "subDistrictName": "ตลาดน้อย"
      }
    ],
    "districtList": [
      {
      "districtId": "1008",
      "districtName": "ป้อมปราบศัตรูพ่าย",
      "provinceId": "10"
      },
      {
      "districtId": "1013",
      "districtName": "สัมพันธวงศ์",
      "provinceId": "10"
      }
    ],
    "provinceList": [
      {
      "provinceId": "10",
      "provinceName": "กรุงเทพมหานคร"
      }
    ]
}
มาดูโค้ดฉบับเต็มกันเถอะ ...
'// Special Thank ... Original JSON data.
'// https://gist.github.com/mennwebs/8ff8e27a01fd06ca2ac965a1c7317552

Imports Newtonsoft.Json
Imports System.IO

Public Class frmJsonPostCode
    Private JsonSource As New BindingSource()

    Private Sub frmJsonPostCode_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
      '// JSON data as a string
      Dim json = File.ReadAllText(MyPath(Application.StartupPath) & "src\th-address.json")
      '// Deserialize JSON into a List(Of LocationData)
      Dim dataList As List(Of LocationData) = JsonConvert.DeserializeObject(Of List(Of LocationData))(json)
      Dim DT As New DataTable()
      '// Add Columns to DataTable.
      With DT.Columns
            .Add("zipCode", GetType(String))
            .Add("subDistrictId", GetType(String))
            .Add("subDistrictName", GetType(String))
            .Add("districtId", GetType(String))
            .Add("districtName", GetType(String))
            .Add("provinceId", GetType(String))
            .Add("provinceName", GetType(String))
      End With
      '// Loop for add row data to DataTable.
      Try
            For Each LocationData In dataList
                For Each subDistrict In LocationData.subDistrictList
                  Dim row As DataRow = DT.NewRow()
                  row("zipCode") = LocationData.zipCode
                  row("subDistrictId") = subDistrict.subDistrictId
                  row("subDistrictName") = subDistrict.subDistrictName
                  '//
                  Dim matchingDistrict = LocationData.districtList.FirstOrDefault(Function(d) d.districtId = subDistrict.districtId)
                  If matchingDistrict IsNot Nothing Then
                        row("districtId") = matchingDistrict.districtId
                        row("districtName") = matchingDistrict.districtName
                  End If
                  '//
                  Dim matchingProvince = LocationData.provinceList.FirstOrDefault(Function(p) p.provinceId = subDistrict.provinceId)
                  If matchingProvince IsNot Nothing Then
                        row("provinceId") = matchingProvince.provinceId
                        row("provinceName") = matchingProvince.provinceName
                  End If
                  DT.Rows.Add(row)
                Next
            Next
      Catch ex As Exception
            MessageBox.Show(ex.Message)
      End Try
      '// Set DataTable as the DataSource for BindingSource.
      JsonSource.DataSource = DT
      '// Set BindingSource as the DataSource for DataGridView.
      dgvData.DataSource = JsonSource
      '// Remove some columns.
      With dgvData.Columns
            .Remove("subDistrictId")
            .Remove("districtId")
            .Remove("provinceId")
      End With
      '//
      With dgvData
            .Columns("zipCode").HeaderText = "รหัสไปรษณีย์"
            .Columns("subDistrictName").HeaderText = "ตำบล/แขวง"
            .Columns("districtName").HeaderText = "อำเภอ/เขต"
            .Columns("provinceName").HeaderText = "จังหวัด"
      End With
      Call SetupGridView()
      Me.lblRecordCount.Text = "Total: " & Format(dgvData.RowCount, "#,##") & " Records."
    End Sub

    ' / --------------------------------------------------------------------------------
    '// Filter data.
    ' / --------------------------------------------------------------------------------
    Private Sub txtFilterJson_TextChanged(sender As Object, e As System.EventArgs) Handles txtFilterJson.TextChanged
      If rdoFilterAll.Checked Then
            '// Filter for All.
            JsonSource.Filter = _
                " provinceName LIKE " & "'%" & txtFilterJson.Text & "%'" & _
                " OR districtName LIKE " & "'%" & txtFilterJson.Text & "%'" & _
                " OR subDistrictName LIKE " & "'%" & txtFilterJson.Text & "%'" & _
                " OR zipCode LIKE " & "'%" & txtFilterJson.Text & "%'"
            '// Filter ProvinceName.
      ElseIf rdoProvinceName.Checked Then
            JsonSource.Filter = "provinceName LIKE " & "'%" & txtFilterJson.Text & "%'"
            '// Filter DistrictName.
      ElseIf rdoDistrictName.Checked Then
            JsonSource.Filter = "districtName LIKE " & "'%" & txtFilterJson.Text & "%'"
            '// Filter SubDistrictName.
      ElseIf rdoSubDistrictName.Checked Then
            JsonSource.Filter = "subdistrictName LIKE " & "'%" & txtFilterJson.Text & "%'"
            '// Filter ZipCode.
      ElseIf rdoZipCode.Checked Then
            JsonSource.Filter = "zipCode LIKE " & "'%" & txtFilterJson.Text & "%'"
      End If
      '//
      Me.lblRecordCount.Text = "Total: " & Format(dgvData.RowCount, "#,##") & " Records."
    End Sub

    Private Sub rdoFilterAll_CheckedChanged(sender As System.Object, e As System.EventArgs) Handles rdoFilterAll.CheckedChanged
      txtFilterJson.Focus()
    End Sub

    Private Sub rdoProvinceName_CheckedChanged(sender As System.Object, e As System.EventArgs) Handles rdoProvinceName.CheckedChanged
      txtFilterJson.Focus()
    End Sub

    Private Sub rdoDistrictName_CheckedChanged(sender As Object, e As System.EventArgs) Handles rdoDistrictName.CheckedChanged
      txtFilterJson.Focus()
    End Sub

    Private Sub rdoSubDistrictName_CheckedChanged(sender As Object, e As System.EventArgs) Handles rdoSubDistrictName.CheckedChanged
      txtFilterJson.Focus()
    End Sub

    Private Sub rdoZipCode_CheckedChanged(sender As Object, e As System.EventArgs) Handles rdoZipCode.CheckedChanged
      txtFilterJson.Focus()
    End Sub

#Region "DATAGRIDVIEW"
    '// Initialized DataGridView.
    Private Sub SetupGridView()
      With dgvData
            .RowHeadersVisible = True
            .AllowUserToAddRows = False
            .AllowUserToDeleteRows = False
            .AllowUserToResizeRows = False
            .MultiSelect = False
            .SelectionMode = DataGridViewSelectionMode.FullRowSelect
            .ReadOnly = True
            '// Data rows
            .Font = New Font("Tahoma", 10)
            .RowTemplate.MinimumHeight = 27
            .RowTemplate.Height = 27
            '// Autosize Column
            .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
            '// Header
            With .ColumnHeadersDefaultCellStyle
                .BackColor = Color.RoyalBlue
                .ForeColor = Color.White
                .Font = New Font(dgvData.Font, FontStyle.Bold)
            End With
            .ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing
            .ColumnHeadersHeight = 36
            '/ Accept changes to the header's background color.
            .EnableHeadersVisualStyles = False
            '// Even-Odd Color of Rows.
            .AlternatingRowsDefaultCellStyle.BackColor = Color.Beige
            '// Even-Odd Color of Columns.
            For iCol As Integer = 0 To dgvData.Columns.Count - 1
                '// If any integer Mod by 2 and gets the answer is 0 so even number, 1 is an odd number.
                If iCol Mod 2 = 1 Then
                  dgvData.Columns(iCol).HeaderCell.Style.BackColor = Color.BlueViolet
                Else
                  dgvData.Columns(iCol).HeaderCell.Style.BackColor = Color.SeaGreen
                End If
            Next
      End With
    End Sub
#End Region

#Region "FUNCTION"
    ' / --------------------------------------------------------------------------------
    ' / Get my project path
    ' / AppPath = C:\My Project\bin\debug
    ' / Replace "\bin\debug" with "\"
    ' / Return : C:\My Project\
    Function MyPath(ByVal AppPath As String) As String
      '/ Return Value
      MyPath = AppPath.ToLower.Replace("\bin\debug", "\").Replace("\bin\release", "\").Replace("\bin\x86\debug", "\")
      '// If not found folder then put the \ (BackSlash) at the end.
      If Microsoft.VisualBasic.Right(MyPath, 1) <> Chr(92) Then MyPath = MyPath & Chr(92)
    End Function
#End Region

End Class

'// Define data model classes.
Public Class SubDistrict
    Public Property subDistrictId As String
    Public Property districtId As String
    Public Property provinceId As String
    Public Property subDistrictName As String
End Class

Public Class District
    Public Property districtId As String
    Public Property districtName As String
    Public Property provinceId As String
End Class

Public Class Province
    Public Property provinceId As String
    Public Property provinceName As String
End Class

Public Class LocationData
    Public Property zipCode As String
    Public Property subDistrictList As List(Of SubDistrict)
    Public Property districtList As List(Of District)
    Public Property provinceList As List(Of Province)
End Class

ดาวน์โหลดโค้ดต้นฉบับ VB.NET (2010) ได้ที่นี่ ...


หน้า: [1]
ดูในรูปแบบกติ: [VB.NET] การนำข้อมูลรหัสไปรษณีย์จากรูปแบบ JSON มาแสดงผลลงในตารางกริด และค้นหาข้อมูลได้