Excel转JSON

由于项目需要, 需要将特定的Excel文件提取为JSON, 试了Office2013版本后的插件Excel to JSON后, 发现只能挨个工作表转换, 而且转换效果也不理想;
第二种方法, 将工作表转换成CSV, 再由Java解析, 这样还是得挨个工作表转换, 嫌麻烦.

但是之前看过一点VBA, 所以才鼓足勇气写vb脚本解决问题.

下面的代码由于商业原因, 不能有太多注释, Excel文件也无法提供, 仅以此纪念我的执着.

Sub opRecors2Json()

    Dim recordJsonStr As String
    recordJsonStr = "{"

    Dim totalWorksheets As Long                  ' how many worksheets
    Dim i As Long                                ' loop variable
    Dim j As Long                                ' loop variable
    Dim k As Long                                ' loop variable
    Dim x As Long

    ' const declarations
    Const COLUMN_INDEX_OP_CODE As Long = 3       
    Const COLUMN_INDEX_OP_FIELD As Long = 5      
    Const COLUMN_INDEX_OP_FIELD_CN As Long = 7   
    Const ROW_INDEX_START As Long = 3            

    Dim currWorksheet As Worksheet                  ' current worksheet
    Dim currRow As Range                            ' current row
    Dim currCell As Range                           ' current cell
    Dim currCellValue As String                     ' current cell's value
    Dim currCellMergeCount As Long                  ' current cell's merge's count

    Dim currOpCode As String                        ' operation code
    Dim currOpField As String                       ' api field
    Dim currOpFieldCN As String                     ' api field's Chinese

    Dim worksheetName As String                     ' curr worksheet name
    Dim totalRows As Long                           ' how many rows in current worksheet
    Dim totalColumns As Long                        ' how many columns in current worksheet

    totalWorksheets = Worksheets.Count

    Const OFFSET_FIELD_OP_CODE As Integer = COLUMN_INDEX_OP_FIELD - COLUMN_INDEX_OP_CODE
    Const OFFSET_FIELD_CN_OP_CODE As Integer = COLUMN_INDEX_OP_FIELD_CN - COLUMN_INDEX_OP_CODE

    For i = 1 To totalWorksheets
        Set currWorksheet = Worksheets(i)
        worksheetName = currWorksheet.Name

        ' filter worksheet
        If (StrComp(trim2(worksheetName), "notNeededWorkSheet", vbTextCompare) = 0) Then
            GoTo notValidWorksheet     
        End If

        totalRows = currWorksheet.Range("A65535").End(xlUp).Row
        totalColumns = currWorksheet.Range("IV4").End(xlToLeft).Column
        ' printMsg (worksheetName & ": " & totalRows & ": " & totalColumns)
        ' printMsg ("------------------------------------")

        For j = ROW_INDEX_START To totalRows                ' ignore first tow rows

            For k = COLUMN_INDEX_OP_CODE To totalColumns    ' ignore first one columns (sequence and api)

                If k <> COLUMN_INDEX_OP_CODE _
                    And k <> COLUMN_INDEX_OP_FIELD _
                    And k <> COLUMN_INDEX_OP_FIELD_CN Then

                    GoTo notNeededColumn                    ' continue
                End If

                Set currCell = currWorksheet.Cells(j, k)    ' 当前单元格
                currCellValue = currCell.Value              ' 当前单元格的值
                currCellMergeCount = currCell.MergeArea.Rows.Count ' 当前单元格合并个数

                If k = COLUMN_INDEX_OP_CODE Then

                    currCellValue = trim2(currCellValue)
                    currOpCode = quoteStr(currCellValue)

                    If VBA.IsNumeric(currCellValue) Then
                        ' currOpCode = CLng(currCellValue)
                        ' printMsg (worksheetName & "-" & j & "th row is number: " & currOpCode & ", merged: " & currCellMergeCount)

                        ' 单行的情况
                        If currCellMergeCount = 1 Then
                            currOpField = quoteStr(trim2(currOpField))
                            currOpFieldCN = quoteStr(trim2(currOpFieldCN))
                            recordJsonStr = recordJsonStr & currOpCode & ":{" & currOpField & ":" & currOpFieldCN & "},"
                        Else
                            recordJsonStr = recordJsonStr & currOpCode & ":{"

                            ' 直接从当前行往下读, 一共currCellMergeCount行
                            For x = 1 To currCellMergeCount
                                currOpField = currWorksheet.Cells(j + x - 1, COLUMN_INDEX_OP_FIELD).Value
                                currOpFieldCN = currWorksheet.Cells(j + x - 1, COLUMN_INDEX_OP_FIELD_CN).Value
                                currOpField = quoteStr(trim2(currOpField))
                                currOpFieldCN = quoteStr(trim2(currOpFieldCN))

                                recordJsonStr = recordJsonStr & currOpField & ":" & currOpFieldCN

                                If x <> currCellMergeCount Then
                                    recordJsonStr = recordJsonStr & ","
                                End If

                            Next
                            recordJsonStr = recordJsonStr & "},"
                        End If
                    End If
                End If
notNeededColumn:
            Next

opCodeIsNull:       
        Next

notValidWorksheet:
    Next

    ' 删除最后一个逗号, 在循环中处理太麻烦, 效率也不高
    recordJsonStr = Left(recordJsonStr, Len(recordJsonStr) - 1)
    recordJsonStr = recordJsonStr & "}"
    write2file (recordJsonStr)

End Sub

Public Sub printMsg(ByVal msg)
    Debug.Print msg
End Sub

Public Function isNullStr(ByRef str As String) As Boolean

    Dim lenOfStr As Long
    lenOfStr = Len(str)

    If lenOfStr = 0 Then
        isNullStr = True
    Else
        isNullStr = False
    End If

End Function

Sub write2file(ByVal content As String)
     Dim objStream As Object
     Set objStream = CreateObject("ADODB.Stream")
     Dim filename As String

     filename = Application.GetSaveAsFilename("recordResult.json", "(*.json),*.json")

     If filename <> "False" Then
        With objStream
            .Type = 2
            .Charset = "UTF-8"
            .Open
            .WriteText content
            .SaveToFile filename, 2
        End With
    Else
        MsgBox "保存失败", vbOKOnly, "保存为json"
    End If

     Set objStream = Nothing
End Sub

' 使用双引号包裹字符串
Public Function quoteStr(ByRef str As String) As String
    quoteStr = Chr(34) & str & Chr(34)
End Function

' 有的字段说明中有换行, 英文双引号, 导致出错
' 故写此函数
Function trim2(ByVal str As String) As String

    str = Trim(str)
    str = Replace(str, Chr(34), "")
    str = Replace(str, Chr(13), "")
    str = Replace(str, Chr(10), "")

    trim2 = str
End Function

欢迎拍砖.

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值