I'm a VBA novice trying to combine these two sub procedures into a single procedure - can anyone provide how to do this?
Basically, I'm trying to add an image to an Access report (in the 2nd code block - it's checking/creating the image path) - where there is already a check for other information from the database product record.
Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
Dim x$, y$, i%
x = ""
For i = 1 To 10
y = Me("txtOp" & i) & ""
If y > "" Then
If x > "" Then x = x & " "
x = x & "Option " & i & ": " & y
End If
Next
If x > "" Then x = CR & x
Me.txtProduct = Me.txtItem & "" & x
If Me.Adjustment Then
Me.txtShowSKU = ""
Else
Me.txtShowSKU = Me.txtSKU
End If
Dim x, y, OK%
OK = False
x = Me.txtImage & ""
If x > "" Then
y = getparm("ImagePath")
If y > "" Then
If Right$(y, 1) <> "\" Then y = y & "\"
If Left$(x, 1) = "\" And Len(x) > 1 Then x = Mid$(x, 2)
If FileExists(y & x) Then OK = True: x = y & x
End If
If OK Then
Me.imgProd.visible = True
Me.imgProd.Picture = x
Else
Me.imgProd.visible = False
End If
End If
End Sub
I think this should work:
Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
Dim x as String
Dim y as String
Dim i as Integer
For i = 1 To 10
y = Me("txtOp" & i) & ""
If y > "" Then
If x > "" Then x = x & " "
x = x & "Option " & i & ": " & y
End If
Next
If x > "" Then x = CR & x
Me.txtProduct = Me.txtItem & "" & x
If Me.Adjustment Then
Me.txtShowSKU = ""
Else
Me.txtShowSKU = Me.txtSKU
End If
Dim OK as Boolean
y = ""
x = Me.txtImage & ""
If x > "" Then
y = getparm("ImagePath")
If y > "" Then
If Right$(y, 1) <> "\" Then y = y & "\"
If Left$(x, 1) = "\" And Len(x) > 1 Then x = Mid$(x, 2)
If FileExists(y & x) Then OK = True: x = y & x
End If
If OK Then
Me.imgProd.visible = True
Me.imgProd.Picture = x
Else
Me.imgProd.visible = False
End If
End If
End Sub
Related
I am giving a spreedsheet and I need to convert into JSON.
I have the following spreadsheet as so:
In essence, I'd need to convert into like this:
{ "CompanyA": {
"Products": ["Beds", "Knifes", "Spoons"]
}, "CompanyB": {
"Products": ["Beds", "Knifes", "Spoons"],
"Sites": ["West Coast", "East Coast"]
}, "CompanyC": {
"Office": ["Los Angeles"]
}}
I tried looking at online sources, but I haven't got a good solution to what I am looking for
Here's some basic code which should point you to the right direction.
I have commented it as much as possible.
Sub GetJSONOutput()
Dim wks As Worksheet: Set wks = ActiveSheet
Dim lngLastRow As Long, i As Long, j As Long, k As Long
Dim blFirstRow As Boolean
Dim strOut As String
lngLastRow = wks.Cells.Find("*", wks.Cells(1, 1), , , , xlPrevious).Row
k = 1
For i = 1 To lngLastRow
'\\ First Element - Column A
'\\ Check for first line and build beginning style
If Len(wks.Cells(i, 1).Value) > 0 Then
If blFirstRow = False Then
strOut = "{ """ & wks.Cells(i, 1).Value & """: {"
blFirstRow = True
Else '\\ Rest follow the same style
strOut = "}, """ & wks.Cells(i, 1).Value & """: {"
End If
wks.Cells(k, 4).Value = strOut: k = k + 1 '--> Output Column D
End If
'\\ Middle element - Column B
If Len(wks.Cells(i, 2).Value) > 0 Then strbase = " """ & wks.Cells(i, 2).Value & """: ["
If Len(wks.Cells(i, 3).Value) > 0 Then
'\\ Now we have Middle element then we need to loop through all elements under it!
'\\ Last Element - Column C
If Len(wks.Cells(i + 1, 3).Value) > 0 Then
strAppend = ""
For j = i To wks.Cells(i, 3).End(xlDown).Row
strAppend = strAppend & "|" & wks.Cells(j, 3).Value
Next j
strOut = strbase & """" & Replace(Mid(strAppend, 2, Len(strAppend)), "|", Chr(34) & ", " & Chr(34)) & """]"
wks.Cells(k, 4).Value = strOut: k = k + 1 '--> Output Column D
i = j - 1
Else
strOut = strbase & """" & wks.Cells(i, 3).Value & """]"
wks.Cells(k, 4).Value = strOut: k = k + 1 '--> Output Column D
End If
End If
'\\ Complete output by outputting the last closing brackets
If i = lngLastRow Then
strOut = "}}"
wks.Cells(k, 4).Value = strOut '--> Output Column D
End If
Next i
End Sub
Sub ConvertToJSONText()
Dim Sht As Worksheet
Set Sht = Worksheets("Sheet1")
Dim a As Integer
Dim lstA
Dim lstB
Dim lstC
a = 0
Dim myJsonText
myJsonText = "{"
Do While True
a = a + 1
If Sht.Range("a" & a).Value = "" And Sht.Range("b" & a).Value = "" And Sht.Range("c" & a).Value = "" Then
Exit Do
End If
If Sht.Range("a" & a).Value <> "" And Sht.Range("b" & a).Value = "" And Sht.Range("c" & a).Value = "" Then
If lstB <> "" Then myJsonText = myJsonText & "]"
If lstA <> "" Then myJsonText = myJsonText & "},"
lstA = Sht.Range("a" & a).Value
lstB = ""
lstC = ""
myJsonText = myJsonText & """" & lstA & """: {"
End If
If Sht.Range("a" & a).Value = "" And Sht.Range("b" & a).Value <> "" And Sht.Range("c" & a).Value = "" Then
If lstB <> "" Then myJsonText = myJsonText & "]"
lstB = Sht.Range("B" & a).Value
lstC = ""
myJsonText = myJsonText & """" & lstB & """: ["
End If
If Sht.Range("a" & a).Value = "" And Sht.Range("b" & a).Value = "" And Sht.Range("c" & a).Value <> "" Then
If lstC <> "" Then myJsonText = myJsonText & ","
lstC = Sht.Range("C" & a).Value
myJsonText = myJsonText & """" & lstC & """"
End If
Loop
If lstB <> "" Then myJsonText = myJsonText & "]"
myJsonText = myJsonText & "}"
End Sub
This SELECT CASE scenario is working for me but I think the code can be more friendly ... any advice would be very helpful.
Select Case True 'select case where worker name and action is true then in each case RSworkhours.addnew
Case Me.Worker1.Value <> "" And Me.fw1a1 = 1
With RsWorkHours
.AddNew
!WorkerID = Me.Worker1
!Date = Me.TxtDate
!StandardTime = Me.w1a1s
!Overtime = Me.w1a1o
!Doubletime = Me.w1a1d
!ScaffoldID = Me.cboScaffnum
.Update
End With
Me.fw1a1 = 0
GoTo WorkerHours
Case Me.Worker1.Value <> "" And Me.fw1a2 = 1
With RsWorkHours
.AddNew
!WorkerID = Me.Worker1
!Date = Me.TxtDate
!StandardTime = Me.w1a2s
!Overtime = Me.w1a2o
!Doubletime = Me.w1a2d
!ScaffoldID = Me.cboScaffnum
.Update
End With
Me.fw1a2 = 0
GoTo WorkerHours
The Code iterates through this Select Case 80 times, if there are 16 workers and each have 5 actions.
I was thinking maybe having a loop that modifies the number within the arguments like:
for each x to 16
for each y to 5
If Me.worker & x & .Value <> "" And Me.fw & x & a & y Then
With Recordset
.AddNew
'insert stuff
.Update
End With
End If
Next y
Next x
Does anyone have any insight?
Thank you in advance.
-Matt
You can access all controls by their name from the Controls collection.
Just pass the name of a control and you will get to that control - the name is a string and can of course be dynamic.
Dim x As Long, y As Long
Dim WorkerX As Control, wXaYs As Control, wXaYo As Control, wXaYd As Control
For x = 1 To 16
For y = 1 To 5
Set WorkerX = Me.Controls("Worker" & x)
Set wXaYs = Me.Controls("w" & x & "a" & y & "s")
Set wXaYo = Me.Controls("w" & x & "a" & y & "o")
Set wXaYd = Me.Controls("w" & x & "a" & y & "d")
If WorkerX.Value > "" And wXaYs.Value > "" Then
With Recordset
.AddNew
!WorkerID = WorkerX.Value
!Date = Me.TxtDate
!StandardTime = wXaYs.Value
!Overtime = wXaYo.Value
!Doubletime = wXaYd.Value
!ScaffoldID = Me.cboScaffnum
.Update
End With
End If
Next y
Next x
I have a TreeView with a Click-Event. Since I need to implement a node-oriented dropdown-context-menu by right-click, how may I check in the existing Click-Event if the right mouse-butten was pressed. My Methode so far, looks like this:
Private Sub tvwKategorien_NodeClick(ByVal Node As Object)
Dim sBez1 As String
Dim sLangtext As String
Dim sWKZ As String
Dim sSprache As String
Dim dPreis As Double
If ((Node Is Nothing) = False) Then
If mbParseNodeKeyAndTag(Node) Then
Set moSelectedNode = Node
If msKategorie = frmArtikelgruppenRoot Then
Me.pagKategorie.Visible = False
Me.pagArtikel.Visible = False
Me.pagPicture.Visible = False
Me.pagCrosslinks.Visible = False
Me.SubArtikel.Visible = False
Me.txtKategorie = msKategorie
Me.txtBezeichnung = msBezeichnung
Me.PicArtikel.Visible = False
Call mEnableSubArtikel
Else
If mbIstNodeKategorie(moSelectedNode) Then
Me.pagKategorie.Visible = True
Me.pagArtikel.Visible = False
Me.pagPicture.Visible = False
Me.pagCrosslinks.Visible = False
Me.SubArtikel.Visible = True
Me.txtKategorie = msKategorie
Me.txtBezeichnung = msBezeichnung
Me.PicArtikel.Visible = False
If Node.Child Is Nothing Then
Dim oNodeParam As Node
Set oNodeParam = Node
Call mReadUntergruppen(oNodeParam, oNodeParam.Key, gnCInt(gsParameter(oNodeParam.Text, "Gruppenebene")) + 1)
End If
Call mEnableSubArtikel
Dim rs As Recordset
Set rs = Me.SubArtikel.Form.Recordset
If Not rs Is Nothing Then
Call mReadArtikel(Node, Node.Key, gnCInt(gsParameter(Node.Text, "Gruppenebene")) + 1)
Node.Expanded = True
Else
Node.Expanded = False
End If
Else
Me.pagKategorie.Visible = False
Me.pagArtikel.Visible = True
Me.pagPicture.Visible = True
Me.pagCrosslinks.Visible = True
Me.SubArtikel.Visible = False
Me.txtArtNr = msBezeichnung
Me.txtArt = msBezeichnung & " " & gvntLookup("Matchcode", "KHKArtikel", "Artikelnummer='" & msBezeichnung & "' AND Mandant=" & gnManId, "")
cbBild.Value = "ITPWeb_"
Call mInitPicture
nil = gITPWebGetArtPreis(msBezeichnung, 0, sWKZ, dPreis, cbShop.Value)
Me.txtArtPreis = dPreis
Me.txtArtWkz = sWKZ
If gvntNull2Arg(cboSprache, "") = "" Then
sSprache = "W" & gvntManProperty(22)
Else
sSprache = CStr(cboSprache)
End If
nil = gITPWebGetArtBez(sSprache, msBezeichnung, sBez1, sLangtext)
Me.txtArtBezeichnung = sBez1
Me.txtArtLangtext = sLangtext
msAktuelleKategorie = Split(Node.Key, ";")(0)
Me.cboBonusprodukt.Locked = False
sSplit = Split(Node.Key, ";")
Me.cboBonusprodukt.Value = gvntLookup("BonusProduct", "ITPWebKategorienArtikel", "Artikelnummer=" & gsStr2Sql(msBezeichnung) & " AND Mandant=" & gnManId & " and Kategorie = " & gsStr2Sql(msAktuelleKategorie) & " and Pos = " & sSplit(getArrayLenght(sSplit)), 0)
Me.cboBonusprodukt.AllowValueListEdits = False
Me.txtBonuspunkte = gvntNull2Arg(gvntLookup("Bonuspunkte", "ITPWebKategorienArtikel", "Artikelnummer=" & gsStr2Sql(msBezeichnung) & " AND Mandant=" & gnManId & " and Kategorie = " & gsStr2Sql(msAktuelleKategorie) & " and Pos = " & sSplit(getArrayLenght(sSplit)), 0), 0)
Me.chkOrderable = gvntLookup("USER_ITPWebOrderable", "KHKArtikel", "Artikelnummer=" & gsStr2Sql(msBezeichnung) & " AND Mandant=" & gnManId, -1)
Me.chkShopActive = gvntLookup("USER_ITPWebShopActive", "KHKArtikel", "Artikelnummer=" & gsStr2Sql(msBezeichnung) & " AND Mandant=" & gnManId, -1)
Me.chkPricePush = gvntLookup("USER_ITPWebPricePush", "KHKArtikel", "Artikelnummer=" & gsStr2Sql(msBezeichnung) & " AND Mandant=" & gnManId, 0)
Call mEnableSubCrosslinks
End If
End If
End If
End If
tvwKategorien_NodeClick_Error:
End Sub
I'm working inside an access-document with VBA :(
You have to use MouseDown event for your tree tvwKategorienand flag some module variable in order to check later it in NodeClick
put this at the beginning of the Module but after Option strings
private MouseButton as Integer
Add MouseDown event
Private Sub tvwKategorien_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Long, ByVal y As Long)
MouseButton =Button
End Sub
Then use such condition to detect right click in your existing NodeClick event
If MouseButton = acRightButton Then ' right
and
If MouseButton = acLeftButton Then ' left
i need to get a list of all possible combinations, not permutations.
to make sure i have the right name, 123 and 321 to me are the same thing and should only be listed once.
the code below does what i need but i can't convert it into MS Access vba.
i'm sorry, i know this is basic and it has been asked a million times but i can't find anything for MS Access that works for me.
Sub test_print_nCr()
print_nCr 7, 3, Range("A1")
End Sub
2.
Public Function print_nCr(n As Integer, r As Integer, p As Range)
c = 1
internal_print_nCr n, r, p, 1, 1
End Function
3.
Public Function internal_print_nCr(n As Integer, r As Integer, ByVal p As Range, Optional i As Integer, Optional l As Integer) As Integer
' n is the number of items we are choosing from
' r is the number of items to choose
' p is the upper corner of the output range
' i is the minimum item we are allowed to pick
' l is how many levels we are in to the choosing
' c is the complete set we are working on
If n < 1 Or r > n Or r < 0 Then Err.Raise 1
If i < 1 Then i = 1
If l < 1 Then l = 1
If c < 1 Then c = 1
If r = 0 Then
p = 1
Exit Function
End If
Dim x As Integer
Dim y As Integer
For x = i To n - r + 1
If r = 1 Then
If c > 1 Then
For y = 0 To l - 2
If p.Offset(c - 1, y) = "" Then p.Offset(c - 1, y) = p.Offset(c - 2, y)
Next
End If
p.Offset(c - 1, l - 1) = x
c = c + 1
Else
p.Offset(c - 1, l - 1) = x
internal_print_nCr n, r - 1, p, x + 1, l + 1
End If
Next
End Function
thank you again
I am not sure if this is the best method to do this, but I would use a kind of binary representation. For instance, consider the word "boy" with the number of letters n=3. This word has three letters, so you can use something like this:
001 = y,
010 = o,
011 = oy,
100 = b,
101 = by,
110 = bo,
111 = boy.
The left side can be done with a loop from i=1 to power(2,n)-1 and transforming i to a number in the binary basis. So, the only thing you have to do is to use the non null positions to build your combinations.
Probably there is something more interesting than this in Knuth.
i found this code here, and it gives me exactly what i need. you just have to create a table with numbers from 1-100. instructions at the link below
enter link description here
thank you everyone
Public Sub buildquery(strN As String, K As Integer)
Dim qd As DAO.QueryDef
Dim intI As Integer
Dim strsql As String
Dim strSelect As String
Dim strFrom As String
Dim strWhere As String
Set qd = CurrentDb.QueryDefs("QN")
qd.sql = "SELECT N FROM tblN WHERE N IN (" & strN & ")"
Set qd = Nothing
strSelect = "SELECT QN.N "
strFrom = "FROM QN "
strWhere = "WHERE QN_1.N > QN.N "
For intI = 1 To K - 1
strSelect = strSelect & ", QN_" & intI & ".N AS N" & intI & " "
strFrom = strFrom & ", QN AS QN_" & intI & " "
If intI < K - 1 Then
strWhere = strWhere & " AND QN_" & intI + 1 & ".N > QN_" & intI & ".N "
End If
Next
strsql = strSelect & " INTO tblCombinations " & strFrom & strWhere
DoCmd.SetWarnings False
DoCmd.RunSQL strsql
DoCmd.SetWarnings True
End Sub
then test
Public Sub testbuildquery()
buildquery "1,2,3,4,5,6,7", 3
End Sub
I have three textboxes and I get their value like this:
Dim X, Y, W As Double
X = DLookup("Summ", "tblPlatej", "ID= " & Form_frmPlatej!ID)
Y = DLookup("Deposit_before", "tblPlatej", "ID= " & Form_frmPlatej!ID)
W = DLookup("Monthly_payment", "tblPlatej", "ID= " & Form_frmPlatej!ID)
But when I change the value of textbox like this
Form_frmPlatej.Deposit_before = X - W + Y
I get a Type mismatch error. All textboxes are currency. How do I calculate new record and put that number in the "Deposit_before" textbox?
Summ, Deposit_before, Monthly_payment are currency data type in my table. Deposit_before is mostly negative.
Here is my whole code for button click
Private Sub Command13_Click()
a1 = DLookup("Inhabitant", "tblClient", "ID = " & Form_frmMain!ID)
B1 = DLookup("PriceTBO", "tblPrice")
c1 = DLookup("Republican", "tblClient", "ID = " & Form_frmMain!ID)
d1 = DLookup("Regional", "tblClient", "ID = " & Form_frmMain!ID)
e1 = DLookup("Local", "tblClient", "ID = " & Form_frmMain!ID)
A = DLookup("IDP", "tblPlatej", "ID= " & Form_frmPlatej!ID)
B = DLookup("Type_of_payment", "tblPlatej", "ID= " & Form_frmPlatej!ID)
C = DLookup("Year", "tblPlatej", "ID= " & Form_frmPlatej!ID)
D = DLookup("Month", "tblPlatej", "ID= " & Form_frmPlatej!ID)
Y = DLookup("Deposit_before", "tblPlatej", "ID= " & Form_frmPlatej!ID) // Problem here
W = DLookup("Monthly_payment", "tblPlatej", "ID= " & Form_frmPlatej!ID) //Problem here
X = DLookup("Summ", "tblPlatej", "ID= " & Form_frmPlatej!ID)
i = Form_frmPlatej.Month.ListIndex
j = Form_frmPlatej.Year.ListIndex
den = DLookup("Date", "tblPlatej", "IDP = " & Form_frmPlatej!IDP)
If X <> " " Then
With Me.Recordset
If Me.Recordset.BOF = False And Me.Recordset.EOF = False Then
.MoveFirst
End If
.AddNew
.Edit
Form_frmPlatej.Deposit_before = X - W + Y //Problem here
Form_frmPlatej.IDP = A + 1
Form_frmPlatej.Type_of_payment = B
If i = 11 Then
Form_frmPlatej.Year = Year.ItemData(j + 1)
i = -1
Else
Form_frmPlatej.Year = Year.ItemData(j)
End If
Form_frmPlatej.Month = Month.ItemData(i + 1)
Form_frmPlatej.Date = DateAdd("m", 1, den)
If c1 <> 0 Then
Form_frmPlatej.Monthly_payment = (a1 * B1) - (c1 * (a1 * B1)) / 100
ElseIf d1 <> 0 Then
Form_frmPlatej.Monthly_payment = (a1 * B1) - (d1 * (a1 * B1)) / 100
ElseIf e1 <> 0 Then
Form_frmPlatej.Monthly_payment = (a1 * B1) - (e1 * (a1 * B1)) / 100
Else
Form_frmPlatej.Monthly_payment = a1 * B1
End If
.Update
End With
Else
MsgBox ("Please enter number")
End If
End Sub
I am completely confused.
I bet your problem is the following. When you say this:
Dim X, Y, W As Double
you think you've done this:
Dim X As Double, Y As Double, W As Double
but what you've really done is this:
Dim X
Dim Y
Dim W As Double
This is a classic VBA mistake. Most VBA programmers have made it, and that's why most VBA programmers fall back on declaring only one variable per Dim statement (i.e. one per line). Otherwise it's way too easy to make that mistake, and difficult to spot it afterwards.
So with Dim X and Dim Y you've implicitly declared X and Y as Variant type (equivalent to Dim X As Variant and Dim Y As Variant).
Why does this matter? When you then say this:
X = DLookup("Summ", "tblPlatej", "ID= " & Form_frmPlatej!ID)
Y = DLookup("Deposit_before", "tblPlatej", "ID= " & Form_frmPlatej!ID)
maybe one of those two DLookup unexpectedly returns something that isn't a number, for example a string. Your variant X or Y will accept this without complaining; the Variant acquires the type of the thing on the right hand side of the assignment.
However, when you try to do math with these values, X - W + Y will throw a type mismatch error if X and/or Y is a string.
See also this earlier answer of mine, from which I reused some of the wording: https://stackoverflow.com/a/11089684/119775