How do I properly add items in a multilistbox? - vba

I'm using vba to fetch equipment numbers and their corresponding information and putting them in a listbox. A user will enter in the equipment number they want and excel will fetch the info. However, when I click my 'Get Data' button the first time it works ok. When i do it the second time for another equipment number I get the message "Could not set the List property. Invalid property array index." Here's my code:
Dim value As Long
Public i As Integer
Private Sub GetDataButton_Click()
Dim num As Variant
value = EquipmentNumber.value
For Each num In Sheets("S1 Cvtg Eqt List").Range(Range("B1"), Range("B1").End(xlDown))
If num = value Then
MWOList.AddItem (num)
MWOList.List(i, 1) = (num.Offset(0, 1))
MWOList.List(i, 2) = (num.Offset(0, 2))
MWOList.List(i, 3) = (num.Offset(0, 3))
MWOList.List(i, 4) = (num.Offset(0, 4))
MWOList.List(i, 5) = (num.Offset(0, 5))
i = i + 1
End If
Next num
i = i + 1
End Sub

Try below, please note that I had changed not only "i" declaration, and value to public, but also the List column position starts from 0, so if this is 6 element table, then switch it back.
The reason you had error was in fact another "i" iteration "i=i+1" after the loop, the list rows also start from 0, therefore you added 2nd index, and tried to insert it on the third position.
Public value As Long
Public i As Integer
Private Sub GetDataButton_Click()
Dim num As Variant
value = EquipmentNumber.value
For Each num In Sheets("S1 Cvtg Eqt List").Range(Range("B1"), Range("B1").End(xlDown))
If num = value Then
i = MWOList.ListCount 'set i to available space
MWOList.AddItem
MWOList.List(i, 0) = (num.Offset(0, 1))
MWOList.List(i, 1) = (num.Offset(0, 2))
MWOList.List(i, 2) = (num.Offset(0, 3))
MWOList.List(i, 3) = (num.Offset(0, 4))
MWOList.List(i, 4) = (num.Offset(0, 5))
End If
Next num
EquipmentNumber = ""
End Sub

Related

Min function not working properly in VBA

I'm working on a macro right now and it's producing weird results. The part that is specifically not working is a Min function.
a1RowTemp1 = a1Row
For i = 0 To diff1
intercept = Application.WorksheetFunction.intercept(a(),c())
LinReg1 = (slope * Cells(a1RowTemp1, 1)) + intercept
difference1 = Worksheets("GF9").Cells(a1RowTemp1, 2) - LinReg1
e(i) = difference1
a1RowTemp1 = a1RowTemp1 + 1
Next i
a2RowTemp2 = a2Row
For i = 0 To diff2
intercept2 = Application.WorksheetFunction.intercept(b(), d())
LinReg2 = (slope2 * Cells(a2RowTemp2, 1)) + intercept2
difference2 = Worksheets("GF9").Cells(a2RowTemp2, 2) - LinReg2
f(i) = difference2
a2RowTemp2 = a2RowTemp2 + 1
Next i
Worksheets("Chart").Cells(currentRow, 12) = Application.Max(e())
Worksheets("Chart").Cells(currentRow, 13) = Application.Min(e())
Worksheets("Chart").Cells(currentRow, 25) = Application.Max(f())
Worksheets("Chart").Cells(currentRow, 26) = Application.Min(f())
In the bottom of the code it stores the difference1 and difference2 values in arrays e() and f(). When I use the functions max/min the macro only outputs the correct values for the max functions. I suspect this has something to do with my incorrectly using the arrays.
If e is one dimensional array you should be able to write
Application.WorksheetFunction.Min(e)
Example:
Option Explicit
Public Sub TEST()
Dim e()
e = Array(3, 4, 2, 5)
MsgBox Application.WorksheetFunction.Min(e)
End Sub
If you are still getting the wrong values you need to step though with F8 and check the values being assigned to e in the loop are the expected ones.
You've omitted the declaration and dimensioning of the e and f array. This was an important factor in your problem.
When you declared your e and f as long or double arrays, they were instantiated with zero values.
Dim v() As Double, i As Long
ReDim v(5) '<~~ all zero values
For i = LBound(v) To UBound(v) - 1 '<~~fill all but the last one
v(i) = i + 10
Next i
Debug.Print Application.Min(v) 'zero as v(5) is zero
If you want to ignore array elements that you have not assigned values to, declare the arrays as a variant type.
Dim v() As Variant, i As Long
ReDim v(5) '<~~ all empty values
For i = LBound(v) To UBound(v) - 1 '<~~fill all but the last one
v(i) = i + 10
Next i
Debug.Print Application.Min(v) '10 as v(5) is empty and not considered in Min
An unassigned variant array element is considered empty and is not used in the Min calculation.
Alternately, use one of two methods to remove unused array elements.
'...
'redimension before the loop to the known ubound
redim e(diff1)
For i = 0 To diff1
intercept = Application.WorksheetFunction.intercept(a(),c())
LinReg1 = (slope * Cells(a1RowTemp1, 1)) + intercept
difference1 = Worksheets("GF9").Cells(a1RowTemp1, 2) - LinReg1
e(i) = difference1
a1RowTemp1 = a1RowTemp1 + 1
Next i
'...
'or redimension after the loop with Preserve
For i = 0 To diff2
intercept2 = Application.WorksheetFunction.intercept(b(), d())
LinReg2 = (slope2 * Cells(a2RowTemp2, 1)) + intercept2
difference2 = Worksheets("GF9").Cells(a2RowTemp2, 2) - LinReg2
f(i) = difference2
a2RowTemp2 = a2RowTemp2 + 1
Next i
'i exits with a value 1 greater than diff2
redim preserve f(i-1)
'...

If statement results overwriting each other VBA

I am experiencing a problem with the outputs from my loop. As the sub is running I can see that the results from the final IF statement are being overwritten by the results from the second one. My code is structured as follows:
for i = 1 to 5
for j = 1 to 50
for each events.value in eventArray
if events.value = arrayElem then
if cells(i,j).value = "x" then
type = "col1"
elseif cells(i,j).value = "y" then
date = "col2"
elseif cells(i,j).value = "z" then
num = "col3"
end if
count = count + 1
activeworkbook.worksheets("output").cells(count + 1, 1) = type
activeworkbook.worksheets("output").cells(count + 1, 2) = date
activeworkbook.worksheets("output").cells(count + 1, 3) = num
end if
next arrayElem
if cells(i,j).value = "a" then
name = "row1"
elseif cells(i,j).value = "b" then
size = "row2"
elseif cells(i,j).value = "c" then
height = "row3"
end if
activeworkbook.worksheets("output").cells(count + 2, 1) = name
activeworkbook.worksheets("output").cells(count + 2, 2) = size
activeworkbook.worksheets("output").cells(count + 2, 3) = height
next j
next i
Obviously these are dumby variables and results, but the overall structure is the same as the real code. I can see "name","size", and "height" being printed, but then they get replaced by "type", "date", and "num". How do I prevent this from happening? Each time a new event is found I need it to print its associated characteristics printed into a new row in the "output" sheet.
Consider the following simplified version of your code:
For i = 1 To 100
If x = y Then
rowNum = rowNum + 1
Cells(rowNum + 1, 1) = "A"
End If
Cells(rowNum + 2, 1) = "B"
Next
Each time through the loop you are writing out either one or two things (two if x = y is true, one if it isn't) but you are only incrementing the row number by zero or one (one if x = y is true, zero if it isn't). Even if you know that x will always equal y, you are still trying to write two rows of information out but only increasing the row counter by one.
Assuming you are not trying to replace the "B"s in my example with the "A"s from the next iteration through the loop, you should change the code to something like:
For i = 1 To 100
If x = y Then
rowNum = rowNum + 1
Cells(rowNum, 1) = "A"
End If
rowNum = rowNum + 1
Cells(rowNum, 1) = "B"
Next

Trying to count all symbols and numbers in a word file. Program outputs symbols but not how many times they appear

(Visual Basic)
This is the word file I'm reading from:
`#+/084&"
#3*#%#+
8%203:
,1$&
!-*%
.#&33&
#*#71%
&-&641'2
#))85
9&330*
Download link: http://www.filehosting.org/file/details/465979/words.txt
I am trying to find all the different characters and symbols inside the word files, and then count them, and output them as a frequency. For example ("The symbol '#' appears (8) times"), ("The number(0) appears (3) times") etc.
I am using a 2 dimensional array and storing the symbols in the first column and the amount of times they appear in the second.
This is my current code:
Sub Main()
Dim UncodedWords(10) As String
Dim Symcheck(19, 3) As String
Dim X As Integer = 0
Symcheck(0, 0) = ("+")
Symcheck(0, 1) = ("0")
Symcheck(1, 0) = ("/")
Symcheck(1, 1) = ("0")
Symcheck(2, 0) = ("’")
Symcheck(2, 1) = ("0")
Symcheck(3, 0) = ("&")
Symcheck(3, 1) = ("0")
Symcheck(4, 0) = (":")
Symcheck(4, 1) = ("0")
Symcheck(5, 0) = ("$")
Symcheck(5, 1) = ("0")
Symcheck(6, 0) = ("-")
Symcheck(6, 1) = ("0")
Symcheck(7, 0) = ("!")
Symcheck(7, 1) = ("0")
Symcheck(8, 0) = (".")
Symcheck(8, 1) = ("0")
Symcheck(9, 0) = ("""")
Symcheck(9, 1) = ("0")
Symcheck(10, 0) = ("0")
Symcheck(10, 1) = ("0")
Symcheck(11, 0) = ("1")
Symcheck(11, 1) = ("0")
Symcheck(12, 0) = ("2")
Symcheck(12, 1) = ("0")
Symcheck(13, 0) = ("3")
Symcheck(13, 1) = ("0")
Symcheck(14, 0) = ("4")
Symcheck(14, 1) = ("0")
Symcheck(15, 0) = ("5")
Symcheck(15, 1) = ("0")
Symcheck(16, 0) = ("6")
Symcheck(16, 1) = ("0")
Symcheck(17, 0) = ("7")
Symcheck(17, 1) = ("0")
Symcheck(18, 0) = ("8")
Symcheck(18, 1) = ("0")
Symcheck(19, 0) = ("9")
Symcheck(19, 1) = ("0")
Dim Newtext(10) As String
Dim FileLoc As String = "C:\Users\Downloads\words.txt"
Dim StringReader As New StreamReader(FileLoc, FileMode.Open)
For Counter = 0 To 9 ' for each line in the file
UncodedWords(Counter) = StringReader.ReadLine
Next
For Counter = 0 To 9 ' for each word in the file
For length = 1 To Len(UncodedWords(Counter)) - 1
For Counter2 = 0 To 19 ' for each symbol in symcheck
If UncodedWords(Counter).Contains(Symcheck(Counter2, 0)) Then
X += 1
Else
End If
WriteLine(Symcheck(Counter2, 0))
WriteLine(Symcheck(Counter2, X))
Next
Next
Next
End Sub
End Module
There are a lot of ways to do this.
One simple, though not necessarily efficient, method is to begin with an empty Symcheck. Then check each character in the input string. If you've encountered the character before (i.e., if it's in Symcheck; use IndexOf), increment its counter. Otherwise, add it to Symcheck with zero count.
This is what a hash map (hash table) is used for.
Loop through each character in the txt file, and perform a check. If the key exists in the hash map, then increment that keys value, else add the key with a value of 0.
Psuedocode:
For each letter in txtFile
If (HashMap.KeyExists(letter)) then
HashMap(letter).Value += 1
Else
HashMap.Add(letter, 0)
End If
Next

Working with Excel ranges and arrays

In VBA, I can easily pull in an sheet\range into an array, manipulate, then pass back to the sheet\range. I'm having trouble doing this in VB.Net though.
Here's my code.
Rng = .Range("a4", .Cells(.UsedRange.Rows.Count, .UsedRange.Columns.Count))
Dim SheetArray(,) As Object = DirectCast(Rng.Value(Excel.XlRangeValueDataType.xlRangeValueDefault), Object(,))
For X As Integer = 0 To SheetArray.GetUpperBound(0)
If IsNothing(SheetArray(X, 0)) Then Exit For
SheetArray(X, 6) = SheetArray(X, 3)
SheetArray(X, 7) = CDbl(SheetArray(X, 3).ToString) - CDbl(SheetArray(X, 1).ToString) - _
CDbl(SheetArray(X, 7).ToString)
For Y As Integer = 0 To 3
SheetArray(X, Y * 2 + 1) = Math.Round(CDbl(SheetArray(X, Y * 2 + 1).ToString), 3)
Next
If Math.Abs(CDbl(SheetArray(X, 7).ToString)) > 0.1 Then _
.Range(.Cells(X + 1, 1), .Cells(X + 1, 8)).Font.Color = -16776961
Next
I'm getting an error on the first If IsNothing(SheetArray(X, 0)) Then Exit For
line. It is telling me index is out of bounds of the array. Any idea why? The SheetArray object contains the data, but I just am not sure how to get to it.
In the For you have to loop from 0 to Count - 1:
For X As Integer = 0 To SheetArray.GetUpperBound(0) - 1
'...
Next
That will fix your problem.

EDI file without any third party tool

i am getting EDI file as shown below,i need to process it ,and i need to maintain primary key ,foreign key also.
TH*4.2*857463*01**20091015*1045*P**~~IS*7564*ACME
PHARMACY~PHA*1234567890~PAT*MA*06*987544****SMITH*JOHN****1234 MAIN
ST**SOMEWHERE*MA*54356**19500101*M*01*01*INDIA**BURGER~
Here the column delimeter is * ,also if no value is provided they also put *.
i need to store fields from
TH*4.2*857463*01**20091015*1045*P**~~
into 1 table,by seperating fields.
So it would be
th01 th02 th03 th04 th05 th06 th07 th08 th09 th10
TH 4.2 857163 01 *(no value) 20091015 1045 p * (novalue) ~~
IS*7564*ACME PHARMACY into another table,and so on.
i cannot use third party tool as i cannot have xml files
Any help?
ok.
here is my vb.net code
Public Enum Segments
TH
PHA
PAT
IS1
End Enum
Dim arrLine As String()
Dim segmentcode As String
Dim counter As Integer
Dim linenumber As Integer = 1
Dim segmenetsequence As Hashtable = New Hashtable()
Dim setid As Guid = Guid.NewGuid()
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
arrLine = Row.LineText.Split("*"c)
segmentcode = SegmentValue(arrLine, 0)
Row.LineNumber = linenumber
Row.Setid = setid
counter = arrLine.Length
linenumber += 1
Select Case (segmentcode.ToUpper())
Case Segments.TH.ToString.ToUpper()
Row.TH01 = SegmentValue(arrLine, 1)
Row.TH02 = SegmentValue(arrLine, 2)
Row.TH03 = Convert.ToInt32(SegmentValue(arrLine, 3))
Row.TH04 = SegmentValue(arrLine, 4)
Row.TH05 = Convert.ToDateTime(SegmentValue(arrLine, 5))
Row.TH06 = SegmentValue(arrLine, 6)
Row.TH07 = SegmentValue(arrLine, 7)
Row.TH08 = Convert.ToInt32(SegmentValue(arrLine, 8))
Row.TH09 = SegmentValue(arrLine, 9)
Case Segments.IS1.ToString.ToUpper()
Row.IS01 = SegmentValue(arrLine, 1)
Row.IS02 = SegmentValue(arrLine, 2)
Row.IS03 = SegmentValue(arrLine, 3)
Case Segments.PHA.ToString.ToUpper()
Row.PHA01 = SegmentValue(arrLine, 1)
Row.PHA02 = SegmentValue(arrLine, 2)
Row.PHA03 = SegmentValue(arrLine, 3)
Row.PHA04 = SegmentValue(arrLine, 4)
Row.PHA05 = SegmentValue(arrLine, 5)
Row.PHA06 = SegmentValue(arrLine, 6)
Row.PHA07 = SegmentValue(arrLine, 7)
Row.PHA08 = SegmentValue(arrLine, 8)
Row.PHA09 = SegmentValue(arrLine, 9)
Row.PHA10 = SegmentValue(arrLine, 10)
Row.PHA11 = SegmentValue(arrLine, 11)
Row.PHA12 = SegmentValue(arrLine, 12)
Case Segments.PAT.ToString.ToUpper()
Row.PAT01 = SegmentValue(arrLine, 1)
Row.PAT02 = SegmentValue(arrLine, 2)
Row.PAT03 = SegmentValue(arrLine, 3)
Row.PAT04 = SegmentValue(arrLine, 4)
Row.PAT05 = Convert.ToInt32(SegmentValue(arrLine, 5))
Row.PAT06 = SegmentValue(arrLine, 6)
Row.PAT07 = SegmentValue(arrLine, 7)
Row.PAT08 = SegmentValue(arrLine, 8)
Row.PAT09 = SegmentValue(arrLine, 9)
Row.PAT10 = SegmentValue(arrLine, 10)
Row.PAT11 = SegmentValue(arrLine, 11)
Row.PAT12 = SegmentValue(arrLine, 12)
Row.PAT13 = SegmentValue(arrLine, 13)
Row.PAT14 = SegmentValue(arrLine, 14)
Row.PAT15 = SegmentValue(arrLine, 15)
Row.PAT16 = SegmentValue(arrLine, 16)
Row.PAT17 = SegmentValue(arrLine, 17)
Row.PAT18 = Convert.ToDateTime(SegmentValue(arrLine, 18))
Row.PAT19 = SegmentValue(arrLine, 19)
Row.PAT20 = Convert.ToInt32(SegmentValue(arrLine, 20))
Row.PAT21 = Convert.ToInt32(SegmentValue(arrLine, 21))
Row.PAT22 = SegmentValue(arrLine, 22)
Row.PAT23 = SegmentValue(arrLine, 23)
Row.PAT24 = SegmentValue(arrLine, 24)
End Select
End Sub
Public Function SegmentValue(ByRef LineArray As String(), ByVal Counter As Integer) As String
Throw New NotImplementedException
If LineArray.Length > Counter Then
Return LineArray(Counter).ToString().Trim()
End If
Return String.Empty
End Function
End Class
Speaking in broad terms, I would look at using a Script Component as a source. It would have an output collection per "thing" the file could contain. In your example, you'd have Output 0 with sufficient columns to describe the th rows above. You'd then have an Output 1 collection that describes the IS data set. You'll also need to factor in any keys, possibly surrogate keys generated within the source component to keep track of your data.
Once you've defined the all the columns in the collections, then it's a simple matter of writing the parsing logic in C#/VB.NET. Once parsed, you simply assign values into those collections.
Output0Buffer.AddRow();
// use this to assign a value
Output0Buffer.MyColumn = parsedValue;
// Use this for handling a null value
Output0Buffer.MyColumn_IsNull = true;
Now you can run the package and parsed data flows down the stream.
It sounds like you have foreign keys to be satisfied and surrogate values to be generated. If that is the case, I'd write most, if not all this data into a variety of staging tables and then proceed with validation and backfilling of data through repeated queries via Execute SQL Tasks chained to the Data Flow Task.
Need more detail? Edit your question and provide some yourself. We're all happy to give advice and direction but we are not in your cube and do not understand your needs.