JSON to CSV Conversion Gone Wrong: Got a Single Line of 991 Entrieswith Cells In Between. How Do I F

J

joeu2004

Alex Salkever said:
So I was attempting to convert a JSON to a CSV and rather
than output as vertical rows it interpreted so as to put
all the cells in a single row. What a mess. This is,
basically, a pattern of 4-5 cells with valid data followed
by 3 empty cells. How do I fix this?

Perhaps the macro below does what you want.

Even though it should not overwrite any existing data, it would be prudent
to make a backup copy of the Excel file first. Then:

1. Right-click on the worksheet tab "ASPCA1", and click on View Code.
2. Copy the text of the macro below, and paste into left pane of VBA window.
3. Put the cursor on a line of the macro in the VBA window, and press F5 to
execute the macro.

The macro creates a new worksheet "new ASPCA1" with the data rearranged the
way that I believe you intended. If not, let me know what you need changed.

Note: The macro AutoFits the columns. That makes for some very wide
columns due to the hyperlinks. If you do not want that, remove or comment
out the AutoFit statement near the end of the macro.

If you want to save the macro with the file, save the file as macro-enabled
(xlsm).

If you no longer need the macro, press ctrl-A to select the entire macro,
then press Delete. That will allow you to save the file as
non-macro-enabled (xlsx).

The macro....

Sub doit()
Dim oldData As Range, myErr As Long
Dim newName As String, newRow As Long, nCol As Long

Set oldData = Me.Range("a1")

' create new worksheet
newName = "new " & Me.Name
Sheets.Add after:=Sheets(Sheets.Count)
On Error Resume Next
ActiveSheet.Name = newName
myErr = Err
On Error GoTo 0
If myErr <> 0 Then
Application.DisplayAlerts = False
Sheets(newName).Delete
Application.DisplayAlerts = True
ActiveSheet.Name = newName
End If

' copy old data to new worksheet.
' each contiguous column goes into a new row
newRow = 0
nCol = Columns.Count
Do
newRow = newRow + 1
Me.Range(oldData, oldData.End(xlToRight)).Copy _
Destination:=ActiveSheet.Cells(newRow, "a")
Set oldData = oldData.End(xlToRight).End(xlToRight)
Loop Until oldData.Column = nCol

' remove next line if you do not want AutoFit
ActiveSheet.UsedRange.EntireColumn.AutoFit
MsgBox "done"
End Sub
 
G

GS

So I was attempting to convert a JSON to a CSV and rather than output
as vertical rows it interpreted so as to put all the cells in a
single row. What a mess. This is, basically, a pattern of 4-5 cells
with valid data followed by 3 empty cells.

How do I fix this? It's not a standard transpose.

Here's the file.

https://docs.google.com/spreadsheets/d/1PlI-DYjssuoD4c-jsT163rQoPXxJgQxzIVfemftDo68/edit?usp=sharing

Thanks!

If you have the original JSON file then this VB-JSON project might be
of interest...

http://www.ediy.co.nz/vbjson-json-parser-library-in-vb6-xidc55680.html

--
Garry

Free usenet access at http://www.eternal-september.org
Classic VB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
 
G

GS

If you *do have* the original JSON file (or string saved in a plain
text file), the following will work if the JSON structure is 'List'
format...


Option Explicit


Sub Parse_JsonList()
Dim vData, v1, v2, vTextOut
Dim sFile$, sMsg$
Dim n&, k&, i&, lMaxCols&, lNum&
Dim bValuesOnly As Boolean

sFile = Application.GetOpenFilename(Title:="Select JSON to parse")
If sFile = "False" Then Exit Sub '//user cancels

sMsg = "Do you want to parse 'values' only, as opposed to
'name:value' pairs?"
bValuesOnly = (MsgBox(sMsg, vbYesNo) = vbYes)

'Get the JSON string from the file,
'filter out unwanted characters,
'and dump the list into an array.
vData = Split(FilterString(ReadTextFile(sFile), "},:"), "},")

'Get the number of cols needed
For n = LBound(vData) To UBound(vData)
lNum = UBound(Split(vData(0), ",")) + 1
lMaxCols = IIf(lNum > lMaxCols, lNum, lMaxCols)
Next 'n

ReDim vTextOut(1 To UBound(vData) + 1, 1 To lMaxCols)
For n = LBound(vData) To UBound(vData)
v1 = Split(vData(n), ",")
For k = LBound(v1) To UBound(v1)
If bValuesOnly Then
vTextOut(n + 1, k + 1) = Split(v1(k), ":")(1)
Else
vTextOut(n + 1, k + 1) = v1(k)
End If 'bValsOnly
Next 'k
'Rebuild vData for output to parsed file
vData(n) = Join(Application.Index(vTextOut, n + 1, 0), ",")
Next 'n

'Optionally, store the data in a normal csv file
'(User may simply cancel dialog to skip this step)
sFile = Application.GetSaveAsFilename(Title:="Choose the output
file")
If Not sFile = "False" Then WriteTextFile Join(vData, vbLf), sFile

'Dump the data into the worksheet
Cells(1, 1).Resize(UBound(vTextOut), UBound(vTextOut, 2)) = vTextOut
ActiveSheet.UsedRange.EntireColumn.AutoFit
End Sub 'Parse_JsonList

Function ReadTextFile$(Filename$)
' Reads large amounts of data from a text file in one single step.
Dim iNum%
On Error GoTo ErrHandler
iNum = FreeFile(): Open Filename For Input As #iNum
ReadTextFile = Space$(LOF(iNum))
ReadTextFile = Input(LOF(iNum), iNum)

ErrHandler:
Close #iNum: If Err Then Err.Raise Err.Number, , Err.Description
End Function 'ReadTextFile()

Sub WriteTextFile(TextOut$, Filename$, _
Optional AppendMode As Boolean = False)
' Reusable procedure that Writes/Overwrites or Appends
' large amounts of data to a Text file in one single step.
' **Does not create a blank line at the end of the file**
Dim iNum%
On Error GoTo ErrHandler
iNum = FreeFile()
If AppendMode Then
Open Filename For Append As #iNum: Print #iNum, vbCrLf & TextOut;
Else
Open Filename For Output As #iNum: Print #iNum, TextOut;
End If

ErrHandler:
Close #iNum: If Err Then Err.Raise Err.Number, , Err.Description
End Sub 'WriteTextFile()

Function FilterString$(ByVal TextIn$, Optional IncludeChars$, _
Optional IncludeLetters As Boolean = True, _
Optional IncludeNumbers As Boolean = True)
' Filters out all unwanted characters in a string.
' Arguments: TextIn The string being filtered.
' IncludeChars [Optional] Any non alpha-numeric
characters to keep.
' IncludeLetters [Optional] Keeps any letters.
' IncludeNumbers [Optional] Keeps any numbers.
'
' Returns: String containing only wanted characters.
' Comments: Works very fast using the Mid$() function over other
methods.

Const sSource As String = "FilterString()"

'The basic characters to always keep by default
Const sLetters As String = "abcdefghijklmnopqrstuvwxyz"
Const sNumbers As String = "0123456789"

Dim i&, CharsToKeep$

CharsToKeep = IncludeChars
If IncludeLetters Then _
CharsToKeep = CharsToKeep & sLetters & UCase(sLetters)
If IncludeNumbers Then CharsToKeep = CharsToKeep & sNumbers

For i = 1 To Len(TextIn)
If InStr(CharsToKeep, Mid$(TextIn, i, 1)) Then _
FilterString = FilterString & Mid$(TextIn, i, 1)
Next
End Function 'FilterString()

--
Garry

Free usenet access at http://www.eternal-september.org
Classic VB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
 
G

GS

Here's a sample of part of the JSON list this code was built for...

{"x":93,"y":138,"z":168,"label":"Air Force
blue"},{"x":240,"y":248,"z":255,"label":"Alice
blue"},{"x":227,"y":38,"z":54,"label":"Alizarin
crimson"},{"x":239,"y":222,"z":205,"label":"Almond"},{"x":229,"y":43,"z":80,"label":"Amaranth"},{"x":255,"y":191,"z":0,"label":"Amber"},{"x":255,"y":126,"z":0,"label":"Amber
(SAE/ECE)"},{"x":255,"y":3,"z":62,"label":"American
rose"},{"x":153,"y":102,"z":204,"label":"Amethyst"},{"x":164,"y":198,"z":57,"label":"Android
Green"},{"x":242,"y":243,"z":244,"label":"Anti-flash
white"},{"x":205,"y":149,"z":117,"label":"Antique
brass"},{"x":145,"y":92,"z":131,"label":"Antique
fuchsia"},{"x":250,"y":235,"z":215,"label":"Antique
white"},{"x":0,"y":128,"z":0,"label":"Ao (English)"}

...and here's the result of running Parse_JsonList with 'name:value'
pairs...

x:93,y:138,z:168,label:AirForceblue
x:240,y:248,z:255,label:Aliceblue
x:227,y:38,z:54,label:Alizarincrimson
x:239,y:222,z:205,label:Almond
x:229,y:43,z:80,label:Amaranth
x:255,y:191,z:0,label:Amber
x:255,y:126,z:0,label:AmberSAEECE
x:255,y:3,z:62,label:Americanrose
x:153,y:102,z:204,label:Amethyst
x:164,y:198,z:57,label:AndroidGreen
x:242,y:243,z:244,label:Antiflashwhite
x:205,y:149,z:117,label:Antiquebrass
x:145,y:92,z:131,label:Antiquefuchsia
x:250,y:235,z:215,label:Antiquewhite
x:0,y:128,z:0,label:AoEnglish

...and here's the result running with 'values only'...

93,138,168,AirForceblue
240,248,255,Aliceblue
227,38,54,Alizarincrimson
239,222,205,Almond
229,43,80,Amaranth
255,191,0,Amber
255,126,0,AmberSAEECE
255,3,62,Americanrose
153,102,204,Amethyst
164,198,57,AndroidGreen
242,243,244,Antiflashwhite
205,149,117,Antiquebrass
145,92,131,Antiquefuchsia
250,235,215,Antiquewhite
0,128,0,AoEnglish

--
Garry

Free usenet access at http://www.eternal-september.org
Classic VB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
 
G

GS

Note that the formatting of the label text for each list item was
deliberately removed for the project, initially. This formatting can be
preserved by changing the CharsToKeep arg for FilterString as
follows...

"},:) ("

--
Garry

Free usenet access at http://www.eternal-september.org
Classic VB Users Regroup!
comp.lang.basic.visual.misc
microsoft.public.vb.general.discussion
 
A

Alex Salkever

Perhaps the macro below does what you want.



Even though it should not overwrite any existing data, it would be prudent

to make a backup copy of the Excel file first. Then:



1. Right-click on the worksheet tab "ASPCA1", and click on View Code.

2. Copy the text of the macro below, and paste into left pane of VBA window.

3. Put the cursor on a line of the macro in the VBA window, and press F5 to

execute the macro.



The macro creates a new worksheet "new ASPCA1" with the data rearranged the

way that I believe you intended. If not, let me know what you need changed.



Note: The macro AutoFits the columns. That makes for some very wide

columns due to the hyperlinks. If you do not want that, remove or comment

out the AutoFit statement near the end of the macro.



If you want to save the macro with the file, save the file as macro-enabled

(xlsm).



If you no longer need the macro, press ctrl-A to select the entire macro,

then press Delete. That will allow you to save the file as

non-macro-enabled (xlsx).



The macro....



Sub doit()

Dim oldData As Range, myErr As Long

Dim newName As String, newRow As Long, nCol As Long



Set oldData = Me.Range("a1")



' create new worksheet

newName = "new " & Me.Name

Sheets.Add after:=Sheets(Sheets.Count)

On Error Resume Next

ActiveSheet.Name = newName

myErr = Err

On Error GoTo 0

If myErr <> 0 Then

Application.DisplayAlerts = False

Sheets(newName).Delete

Application.DisplayAlerts = True

ActiveSheet.Name = newName

End If



' copy old data to new worksheet.

' each contiguous column goes into a new row

newRow = 0

nCol = Columns.Count

Do

newRow = newRow + 1

Me.Range(oldData, oldData.End(xlToRight)).Copy _

Destination:=ActiveSheet.Cells(newRow, "a")

Set oldData = oldData.End(xlToRight).End(xlToRight)

Loop Until oldData.Column = nCol



' remove next line if you do not want AutoFit

ActiveSheet.UsedRange.EntireColumn.AutoFit

MsgBox "done"

End Sub

Thanks you. Going to try this right now.
 
Joined
Jul 16, 2014
Messages
1
Reaction score
0
I'm not sure if you are aware that there are some online tools that can do this. json-csv.com for example
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top