I created a VBA code that enables me to get a string from a website. The string looks like that (json format)
[
{
"CD":151,
"nID":111,
"sNM":"PNAME1",
"GDR":"MA",
"RGN":"MM",
"reID":1,
"status":"RSB",
"NTY":"EG",
"CLNUM":1,
"CLNM":"THIR",
"YER":2022,
"SCHOD":1718,
"STID":2,
"THNM":"BRYYY",
"SCHNO":"HTBAN",
"rCD":6,
"schooL_TYPE":1,
"SGT":1,
"CLCD":3,
"NG1":1,
"NG2":2,
"YCOD":null,
"general":10,
"special":1,
"naT_ID":1,
"GDR_ID":1,
"sGCOD":8,
"sTTY":1,
"obNM":"NTF",
"obID":0,
"STYN":"NTHMY",
"PSNUM":null
},
{
"CD":153,
"nID":222,
"sNM":"ALIIKK",
"GDR":"MA",
"RGN":"MM",
"reID":1,
"status":"RSB",
"NTY":"EG",
"CLNUM":1,
"CLNM":"THIR",
"YER":2022,
"SCHOD":1718,
"STID":2,
"THNM":"SYYYYY",
"SCHNO":"HTBAN",
"rCD":6,
"schooL_TYPE":1,
"SGT":1,
"CLCD":3,
"NG1":1,
"NG2":2,
"YCOD":null,
"general":10,
"special":1,
"naT_ID":1,
"GDR_ID":1,
"sGCOD":8,
"sTTY":1,
"obNM":"NTF",
"obID":0,
"STYN":"NTHMY",
"PSNUM":null
}
]
I am trying to store the data into a collection and arrays
This is my try but I am confused about the line of setting the collection
Dim json As Object, col As Collection
Set json = JSONConverter.ParseJson(sResp)
Set col = json("CD")
Dim a, i As Long
ReDim a(1 To col.Count, 1 To 1)
For i = 1 To col.Count
'a(i, 1) = col.Item(i)("")
Next i
The string should have two persons' data. How can I pares all the data included into two rows?
I got an error Dictionary Key Not Found at this line of JSONConverter module
Option Explicit
Sub demo()
Dim sResp
sResp = "[{'CD':151,'nID':111,'sNM':'PNAME1','GDR':'MA','RGN':'MM','reID':1,'status':'RSB','NTY':'EG','CLNUM':1,'CLNM':'THIR','YER':2022,'SCHOD':1718,'STID':2,'THNM':'BRYYY','SCHNO':'HTBAN','rCD':6,'schooL_TYPE':1,'SGT':1,'CLCD':3,'NG1':1,'NG2':2,'YCOD':null,'general':10,'special':1,'naT_ID':1,'GDR_ID':1,'sGCOD':8,'sTTY':1,'obNM':'NTF','obID':0,'STYN':'NTHMY','PSNUM':null},{'CD':153,'nID':222,'sNM':'ALIIKK','GDR':'MA','RGN':'MM','reID':1,'status':'RSB','NTY':'EG','CLNUM':1,'CLNM':'THIR','YER':2022,'SCHOD':1718,'STID':2,'THNM':'SYYYYY','SCHNO':'HTBAN','rCD':6,'schooL_TYPE':1,'SGT':1,'CLCD':3,'NG1':1,'NG2':2,'YCOD':null,'general':10,'special':1,'naT_ID':1,'GDR_ID':1,'sGCOD':8,'sTTY':1,'obNM':'NTF','obID':0,'STYN':'NTHMY','PSNUM':null}]"
sResp = Replace(sResp, "'", Chr(34))
Dim data As Object, rec As Object, key, fields, arData
Dim n As Long, m As Long, i As Long, j As Long
Set data = JsonConverter.ParseJson(sResp)
fields = data(1).Keys
m = UBound(fields) + 1
n = data.Count ' records
' fill array
ReDim arData(1 To n, 1 To m)
For i = 1 To n
For j = 1 To m
arData(i, j) = data(i)(fields(j - 1))
Next
Next
' dump array
With Sheet1
.Range("A1").Resize(1, m) = fields ' header
.Range("A2").Resize(n, m) = arData
End With
End Sub
I was wrong. The converter also accepts square brackets as the first element, a collection. The suggested additional brackets would not work either, because they create an invalid JSON.
Now CDP1802 has already answered, but I also looked for a correct solution because of my wrong statement (I deleted it so no one else would see it as the truth):
Sub TestJSON()
Dim sResp As String
Dim json As Collection
Dim col As Dictionary
Dim key As Variant
Dim dicts As Long
Dim row As String
sResp = "[{""CD"":151,""nID"":111,""sNM"":""PNAME1"",""GDR"":""MA"",""RGN"":""MM"",""reID"":1,""status"":""RSB"",""NTY"":""EG"",""CLNUM"":1,""CLNM"":""THIR"",""YER"":2022,""SCHOD"":1718,""STID"":2,""THNM"":""BRYYY"",""SCHNO"":""HTBAN"",""rCD"":6,""schooL_TYPE"":1,""SGT"":1,""CLCD"":3,""NG1"":1,""NG2"":2,""YCOD"":null,""general"":10,""special"":1,""naT_ID"":1,""GDR_ID"":1,""sGCOD"":8,""sTTY"":1,""obNM"":""NTF"",""obID"":0,""STYN"":""NTHMY"",""PSNUM"":null},{""CD"":153,""nID"":222,""sNM"":""ALIIKK"",""GDR"":""MA"",""RGN"":""MM"",""reID"":1,""status"":""RSB"",""NTY"":""EG"",""CLNUM"":1,""CLNM"":""THIR"",""YER"":2022,""SCHOD"":1718,""STID"":2,""THNM"":""SYYYYY"",""SCHNO"":""HTBAN"",""rCD"":6,""schooL_TYPE"":1,""SGT"":1,""CLCD"":3,""NG1"":1,""NG2"":2,""YCOD"":null,""general"":10,""special"":1,""naT_ID"":1,""GDR_ID"":1,""sGCOD"":8,""sTTY"":1,""obNM"":""NTF"",""obID"":0,""STYN"":""NTHMY"",""PSNUM"":null}]"
Set json = JsonConverter.ParseJson(sResp)
For dicts = 1 To json.Count
Set col = json(dicts)
For Each key In col.Keys()
'Debug.Print key & ":" & col(key) & ", "
row = row & col(key) & Chr(9)
Next key
Debug.Print row
row = ""
Next dicts
End Sub
I am new to VBA macro and need some experts help on meeting the below requirement.
I got a workbook containing 2 sheets called 'Data' and 'Stats'.
'Data' contains the values as below
'Stats' contains the values as below
On click on the button, I would like to do the below
Get the values in column A in 'Stats' sheet
Find all the matching rows in 'Data' Sheet
Find the smallest start time and put that in 'Stats' sheet against the stage value
Find the biggest end time and that in 'Stats' sheet against the stage value
Final output would be like below
Note: I do not have the MINIFS or MAXIFS in my installation.
Incase you dont have MINIFS and MAXIFS you can use array formulas like so:
={MIN(IF(Stats!A1=Data!$A$1:$A$1000,Data!$C$1:$C$1000))}
and
={MAX(IF(Stats!A1=Data!$A$1:$A$1000,Data!$B$1:$B$1000))}
The {} indicates, that this is a Array-Formula. Enter with Ctrl + Shift + Enter
No VBA needed.
Just use in your Stats worksheet the following formula for Start:
=MINIFS(Data!A:A,Data!C:C,Stats!A:A)
and the following for End:
=MAXIFS(Data!B:B,Data!C:C,Stats!A:A)
Please, the VBA solution, too. It will be very fast, using arrays, processing everything in memory and dropping the result at once:
Sub BringStats()
Dim shD As Worksheet, shS As Worksheet, lastRD As Long, lastRS As Long
Dim arrD, arrS, i As Long, k As Long, dict As Object, El As Variant
Set shD = Worksheets("Data")
Set shS = Worksheets("Stats")
lastRD = shD.Range("A" & rows.count).End(xlUp).row
lastRS = shS.Range("A" & rows.count).End(xlUp).row
arrD = shD.Range("A2:C" & lastRD).Value
arrS = shS.Range("A2:C" & lastRS).Value
Set dict = CreateObject("Scripting.dictionary")
'load the dictionary with unique keys and all corresponding date in a string, as item
For i = 1 To UBound(arrD)
If Not dict.Exists(arrD(i, 3)) Then
dict.Add arrD(i, 3), CDate(arrD(i, 1)) & ";" & CDate(arrD(i, 2))
Else
dict(arrD(i, 3)) = dict(arrD(i, 3)) & "|" & CDate(arrD(i, 1)) & ";" & CDate(arrD(i, 2))
End If
Next
Dim arr As Variant, minTime As Date, minPos As Long
For i = 1 To UBound(arrS)
If dict.Exists(arrS(i, 1)) Then
arr = Split(dict(arrS(i, 1)), "|") 'extract each pair of time stamps
If UBound(arr) > 0 Then
For Each El In arr 'extract the element containing minimum time
If minTime = 0 Then
minTime = TimeValue(Split(El, ";")(0)): minPos = k
Else
If TimeValue(Split(El, ";")(0)) < minTime Then minTime = TimeValue(Split(El, ";")(0)): minPos = k
End If
k = k + 1
Next
arrS(i, 2) = Split(arr(minPos), ";")(0): arrS(i, 3) = Split(arr(minPos), ";")(1) 'load the array with the minimum time correspondent values
Else
arrS(i, 2) = Split(dict(arrS(i, 1)), ";")(0): arrS(i, 3) = Split(dict(arrS(i, 1)), ";")(1)'loading the array in case of only one occurrence
End If
End If
minPos = 0: minTime = 0: k = 0 'reinitialize the used variables
Next i
'drop the processed array at once
shS.Range("A2").Resize(UBound(arrS), UBound(arrS, 2)).Value = arrS
End Sub
There can be a lot of the same 'stage' occurrences...
I have the following code and it gives me the error Type mismatch for the line of code «Split_dt_2 = Split(Split_dt_1, ",")». I'm not able to run through the code with F8 because it gives me the error right away so i can't give the exact value of «Split_dt_1» but it's always a date which has that form : [11/1/2019,12/1/2019].
My goal would be to obtain :
y_Dest = 2019 and m_Des = 11
Sub import_Redeem_Spread()
Workbooks.Open "C:\Users\106400\OneDrive\Documents\FTT\CDOPT_AB.xlsm"
Dim wksSource As Worksheet, wksDest As Worksheet
Set wksSource = Workbooks("CDOPT_AB.xlsm").Sheets(2)
Set wksDest = ThisWorkbook.Sheets(2)
Dim Split_dt_1() As String
Dim Split_dt_2() As String
Dim Split_dt_3() As String
Dim Split_dt_4() As String
nbRows = wksSource.Cells(Rows.Count, 1).End(xlUp).Row
nbDates = wksDest.Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To nbRows
If wksSource.Cells(i, 16) = "CPG Taux Fixe" Then
For m = 7 To nbDates
Split_dt_1 = wksDest.Cells(m, 2)
Split_dt_2 = Split(Split_dt_1, ",")
Split_dt_3 = Split_dt_2(0)
Split_dt_4 = Split(Split_dt_3, "[")
y_Dest = Right(Split_dt_4(1), 4)
m_Dest = Left(Split_dt_4(1), 2)
y_source = Left(Cells(I, 3), 4)
m_Source = Right(Cells(I, 3), 2)
If y_Dest = m_Dest & y_Source = m_Source Then
For n = 4 To 15
wksDest.Cells(m, n) = wksSource.Cells(i, n)
Next n
End If
Next m
End If
Next i
End Sub
I tried «Dim Split_dt_2() As Variant» but it does noes solve the problem
and I tried
Split_dt_1 = wksDest.Cells(m, 2).value
Split_dt_2 = Split(Split_dt_1, ",")
and it still doesn't work
Thanks in advance!
Use a Variant when using Split to create the array instead of Diming it as a String array.
A Variant will take on the properties of an Array when the function you are using returns an Array.
Dim Split_dt_1 As Variant
Split_dt_1 = Split(wksDest.Cells(m, 2), ",")
I would ditch assigning the Arrays and all the intermediate steps altogether:
y_Dest = Year(Split(Split(wksDest.Cells(m, 2), ",")(0), "[")(0))
There are times when having those intermediate steps helps, but IMO, this isn't one of them.
I have a workbook where I want to find the differences of two sheets by looking at the company name and their corporate registration number and then type the differences on the third sheet.
I have tried the code in another workbook with only 143 rows, which works perfectly, but when I try it on the real workbook with 10,000 rows I get a "type mismatch error". Also if I use other columns than the CVR and Firm columns the code also works.
The CVR is numbers and Firms are strings (firm names). I get the
type mismatch error
on the line I marked **. Does somebody know why I get this error?
Sub ComCVR()
Dim CVR1()
Dim CVR2()
Dim Firm1()
Dim Firm2()
Dim n As Long, m As Long
Dim i As Double, j As Double
Dim intCurRow1 As Integer, intCurRow2 As Integer
Dim rng As Range, rng1 As Range
Set rng = ThisWorkbook.Sheets("Last month").Range("A11")
Set rng1 = ThisWorkbook.Sheets("Current month").Range("A11")
n = rng.CurrentRegion.Rows.Count
m = rng1.CurrentRegion.Rows.Count
ReDim CVR1(n)
ReDim Firm1(n)
ReDim CVR2(m)
ReDim Firm2(m)
ThisWorkbook.Sheets("CVR").Range("A1") = "Flyttet CVR"
ThisWorkbook.Sheets("CVR").Range("B1") = "Flyttet Firmanavn"
ThisWorkbook.Sheets("CVR").Range("A1:B1").Interior.ColorIndex = 3
ThisWorkbook.Sheets("CVR").Range("C1") = "Nye CVR"
ThisWorkbook.Sheets("CVR").Range("D1") = "Nye Firmanavn"
ThisWorkbook.Sheets("CVR").Range("C1:D1").Interior.ColorIndex = 4
ThisWorkbook.Sheets("CVR").Range("A1:D1").Font.Bold = True
' Inset data to arrays
For i = 0 To n
CVR1(i) = ThisWorkbook.Sheets("Last month").Cells(12 + i, 5)
Firm1(i) = ThisWorkbook.Sheets("Last month").Cells(12 + i, 4)
Next
For i = 0 To m
CVR2(i) = ThisWorkbook.Sheets("Current month").Cells(12 + i, 5)
Firm2(i) = ThisWorkbook.Sheets("Current month").Cells(12 + i, 4)
Next
intCurRow1 = 2
intCurRow2 = 2
'Old
For i = 0 To n
For j = 0 To m
If Firm1(i) = ThisWorkbook.Sheets("Current month").Cells(12 + j, 4) Then '** Error raised here
Exit For
End If
If j = m Then
ThisWorkbook.Sheets("CVR").Cells(intCurRow1, 1) = CVR1(i)
ThisWorkbook.Sheets("CVR").Cells(intCurRow1, 2) = Firm1(i)
intCurRow1 = intCurRow1 + 1
End If
Next j
Next i
'new
For i = 0 To m
For j = 0 To n
If Firm2(i) = ThisWorkbook.Sheets("Last month").Cells(12 + j, 4) Then
Exit For
End If
If j = n Then
ThisWorkbook.Sheets("CVR").Cells(intCurRow2, 3) = CVR2(i)
ThisWorkbook.Sheets("CVR").Cells(intCurRow2, 4) = Firm2(i)
intCurRow2 = intCurRow2 + 1
End If
Next j
Next i
Columns("A:B").Select
ActiveSheet.Range("$A:$B").RemoveDuplicates Columns:=1, Header:=xlNo
Application.DisplayAlerts = False
Columns("C:D").Select
ActiveSheet.Range("$C:$D").RemoveDuplicates Columns:=1, Header:=xlNo
Application.DisplayAlerts = False
End Sub
Whenever an error happens, the best way is to google it. This is what it says in the documentation of VBA for Type mismatch:
Cause: The variable or property isn't of the correct type. For example, a variable that requires an integer value can't accept a string value unless the whole string can be recognized as an integer.
In the case of the code, it happens, when an array is compared with excel cell. Now the trick - in order to see why it happens, see what is in these:
Debug.Print ThisWorkbook.Sheets("Last month").Cells(12 + i, 4)
Debug.Print Firm1(i)
and the after the error runs, take a look at the immediate window (Ctrl+G). It it quite possible, that there is an error in the excel cell, thus it cannot be compared. This is some easy way to avoid it, if this is the case:
Sub TestMe()
Dim myRange As Range
Set myRange = Worksheets(1).Cells(1, 1)
myRange.Formula = "=0/0"
If Not IsError(myRange) Then
Debug.Print CBool(myRange = 2)
Else
Debug.Print myRange.Address; " is error!"
End If
End Sub
I have a table that has 4 columns:
ID
keyword
Component
NewComponent
The first 3 contain data and the last one does not.
I have the data sorted by keyword then by component.
Looking at the image below:
Original Table:
Expected Result:
So as far as I can see, two loops need to be done:
Loop through keyword
While looping through keyword, loop through components and create new ones
This is the code I have so far, but I have confused myself with all the loops already..
Sub SingleColumnTable_To_Array()
Dim myTable As ListObject
Dim myArray As Variant
Dim x As Long
Dim compArr() As String, kwArr(), newArr()
Set tmpltWkbk = Workbooks("New DB.xlsm")
Set ws1 = tmpltWkbk.Sheets("TableSheet")
Set myTable = ws1.ListObjects("KW_Table")
counterOne = 0
myArray = myTable.DataBodyRange
kwCounter = 1
'keywords
For y = LBound(myArray) To UBound(myArray)
counterTwo = counterTwo + 1
ReDim Preserve kwArr(counterTwo)
kwArr(counterTwo) = myArray(y, 23)
Next y
RemoveDupesDict kwArr, newArr
'components
For x = LBound(myArray) To UBound(myArray)
counterOne = counterOne + 1
ReDim Preserve compArr(counterOne)
compArr(counterOne) = myArray(x, 3)
Next x
For Each kwElement In newArr
For Each compElement In compArr
Counter = 1
Do While kwCounter < Application.CountIf(kwArr, kwElement) + 1
'This is how I imagine I would create the new component name
'Selection.Offset(0, 1).Value = compElement & "." & Counter
Counter = Counter + 1
kwCounter = kwCounter + 1
Loop
End If
Next compElement
Next kwElement
End Sub
As per comment above. Expanded code slightly to add a new column to a table and insert the formula in case you want a VBA solution:
Sub x()
Dim t As ListObject
Set t = Sheets(1).ListObjects("Table1")
t.ListColumns.Add
t.ListColumns(t.DataBodyRange.Columns.Count).DataBodyRange.Formula = "=C2&"".""&COUNTIFS($B$2:B2,B2,$C$2:C2,C2)"
End Sub