working with arrays - vb.net

Ok I am not completing understand this. I am suppose to only Find the total of each column in the last row. Find the grand total in the last cell (the bottom right corner)
Ok i have tried to do the grandtotal but i am not getting what she wants done I have also tried to reverse the arrays but that was wrong to. I am only suppose to add two line one line is find the total of each colums in the last row and to find the grandtotal. Can someone please explain to me what i am doing wrong thank you.
Module Module1
Sub Main()
Dim sum(5, 4) As Integer
Dim row, col As Integer
Dim grandtotal As Integer
For row = 0 To 4
For col = 0 To 3
sum(row, col) = row + col
sum(row, 4) += row + col
Next col
Next row
For row = 0 To 5
For col = 0 To 4
Console.Write(sum(row, col) & vbTab)
Next col
Console.WriteLine()
Next row
End Sub
End Module

It looks like you have a pretty good grasp of the code you need to use, but I think the main issue here is that you're getting a bit confused with what you actually want the code to do. I too am having a hard time deciding what your actual goal here is, as you say one thing but then have code for something slightly different. I'm assuming this is a homework assignment, so I'm not going to give you the code (especially since I'm not 100% sure what code you might need), but I'm more than happy to go through this stepwise as clearly as I can, and hopefully we'll get to the bottom of your confusion.
To clarify your requirements:
You say you're supposed to find the total of each column, and place that total in the last row. According to your code, that would be row 5 (actually the 6th row).
You then say you need the grand total in the last cell, the bottom-right corner. Since you have 5 columns (0-4), that would be a total of the first 4 columns of row 5.
If we imagine the 2D sum array as a matrix, the problem as stated should yield the following:
Desired Matrix http://dl.dropbox.com/u/1497850/Hosted%20Images%20for%20Websites/MatrixDesired.jpg
Where the "x's" are blank (technically 0), since that column is reserved as the "grand total" column (only the bottom-right should be filled in). For reference, this array/matrix will have the following coordinates:
Coordinate Matrix http://dl.dropbox.com/u/1497850/Hosted%20Images%20for%20Websites/MatrixCoords.jpg
However, as you currently have it coded, your sum array will look like this:
Actual Matrix http://dl.dropbox.com/u/1497850/Hosted%20Images%20for%20Websites/MatrixActual.jpg
What you've done in your code is made the final column the "total column" and ignored the final row. In this case, the bottom-right cell would still be the grand total, but you'd be summing the numbers in column 4 rather than in row 5. This goes against what you stated you want to happen, but is pretty easy to correct (especially now that you can see what's actually happening compared to what you want to happen).
However, maybe this is what you actually meant to happen, and you just misphrased the question a bit? (Or maybe this is what you meant by saying you tried to reverse the arrays?) The point is, rows and columns in even semi-large arrays/matrices are generally easily transposed, so it's important to make sure you're using the right terminology at all times.
Edit: Sorry, I misread your second For loop when I first answered, I apologize. I see now that you're printing the sum array out, but your problem was still probably due to the fact that you weren't filling in the array as you expected. Once you fill the array the way you actually want, your printing statement should work just fine.

Related

Check one series value, change corresponding point colour in 2nd series

I have an automated pareto chart working well in Excel.
I want to change it to check if points in the cumulative percentage series have a value of less than 80% and colour the same number point in the count series if this is the case.
Tried this; doesn't throw any errors but also doesn't work.
I think it should be iterating through a list of values, checking if they are <80 then updating the point at the corresponding i in the count series.
Set percVals = paretoChart.Chart.SeriesCollection(percentSeries).Values
For Each i in percVals
If percVals(i) = <80 Then
With paretoChart.Chart.SeriesCollection(countSeries).Points(i)
.Format.Fill.ForeColor.RGB = RGB(0,0,225)
.Format.Line.ForeColor.RGB = RGB(0,0,225)
End With
End If
Next i
The "paretoChart" variable is set earlier in the code and is working fine throughout.
I've tried without the 'with' statement. No difference.
There is a similar question comparing the two values across series, but I don't think I can adapt that to work here. Any ideas appreciated!

Copy row if value of one cell is "x"; and, auto-hide blanks

I'm trying to copy a row, columns A-J, representing a person and associated info, when column J is filled. I'd fill it with either w, x, y or z based on the reason people are away, and I'd like the row (A-J) copied to another sheet as soon as J is filled.
Here's a screenshot with both Excel documents. Please ignore the "Reason" column in the Pers sheet - I know it could be used, but my production one doesn't have this column, and will not. I just used it to illustrate for you guys.
That other sheet (Main) has headers, as you can see, for each reason why people would be away. This one would permanently be displayed on a big-screen TV. So, what I'm trying to do is :
Copy the rows to Main as soon as the "Departed?" row is filled in Pers;
Make sure those rows go into the proper category, in the first blank row;
Ensure each category remains collapsible.
You can see I've tried using the If function (syntax in screenshot). That worked OK, but :
Left blanks;
Biggest one : only worked row-for-row! (Also the cause of reason #1, I suppose...) Past row 11, nothing. Not too sure what to do about that...?
Hope this is somewhat clear? =) Let me know if you have any questions - thanks for your help!

How to do a summation only within specific cells via VBA

In reference to the picture below, I would like to loop through a certain column (Column D in this case) until I hit a specific cell (Yellow cells in this case). In my final spreadsheet I have multiple yellow cells that I would like to target. Once I hit a yellow cell, I would like to start a simple summation of the values one cell to the left of the yellow (Column C). I would like to keep summing the values until I hit a blank cell, which would indicate the end of the set.
Please let me know if you need any more clarification!
Here's some code that should get the job done. However you are going to have to adapt it to however you want to use it.
Dim Summation as Double
For Each Target in Range("D:D")
If Target.Interior.ColorValue = 6 Then
Summation = Summation + Target.Offset(0, -1).Value
End If
Next Target
I hope this helps. However, don't forget about FreeMan's suggestions about good question asking and using the macro recorder!

Copy cells if specific text is found

I seem to have a problem and currently have not found a solution to it, which is why I address this question to you:
Each day I have a list of invoices and orders coming from different suppliers, and the orders are based on part numbers and types.
This list is imported as text and then goes through a macro I made, to arrange everything in cells.
I also need to go through some steps to format this list based on the type of order (ex: windshield, carpets, wheels, etc ). what I usually do is to filter everything and select the order type that I am interested, and then copy on the same row cells with text and formulas from another worksheet, named "template", which is a list of conditions .
Since it varies from day to day, it may not necessarily contain all part types, which is I couldn't use a macro, and I have to continue by hand, and sometimes the list exceeds 200-300 lines.
To give you an example, if E2 has "windshield" I copy in M2 to Q2 a selection of cells from "Template" (M2 to Q2), if "carpets" I copy M3 to Q3, and so on. the list of conditions is around 15 - 20 rows, and sometimes 2 conditions may apply (if order exceeds $5000 I mark it red, if overdue I bold everything, etc) but mainly I copy based on text in coll E.
If this could be copied into a macro, I would really appreciate it, as I need to take some steps every time, like auto-fit, copy header, format the amounts as number (from text), change text color based on order type, etc, and this too takes time.
I hope this information is enough to make an idea about this, and if not, I could post an example of the list I have to work with.
Many thanks in advance for your support
Use Application.Worksheetfunction.Match to find in which row in Template the to-be-copied cells can be found, then copy range M-Q for this row and paste in your file
You are asking too much in one question to get help here. We are best at single issue questions. The text and code below is intended you give you some ideas. If your code does not work, post the relevant part here and explain the difference between what it does and what you want it to do.
The problems you mention do not sound difficult. I would expect basic VBA to be enough to get you started. Are you looking for bits of relevant code without learning VBA. If you are, this is a big mistake. Search the web for "Excel VBA tutorial" or visit a large library and review their Excel VBA Primers. There are many tutorials and books to choose from so select one that is right for you. The time spent learning the basics will quickly repay itself.
Dim RowCrnt As Long
Dim RowLast As Long
With Worksheets("xxxx")
RowLast = .Cells(Rows.Count,"E").End(xlUp).Row
For RowCrnt = 2 to RowLast
' Code to process each row goes here
Next
End With
The above is probably the structure of your code. The For loop will examine each row in turn which will allow you to take relevant actions.
I have used "E" as a column letter because your question suggests column "E" is the most important. However, code that references columns in this way can be very confusing. Worse, if the column positions change, you will have to work carefully through your code changing the column letters. Better to have some statements at the top like this:
Const ColDate As String = "A"
Const ColAmtInv As string = "B"
Const ColAmtPaid As string = "C"
Const ColProdType As String = "E"
With these constants every reference to a column uses a name not a letter. The code is easier to read and, if a column moves, one change to the constant statement will fix the problem.
The Select Case statement is useful:
Select Case .Cells(RowCrnt, ColProdType).Value
Case "carpets"
' code for carpets
Case "windshield"
' code for carpets
Case Else
' Unknown product type
.Cells(RowCrnt, ColProdType).Font.Color = RGB(255, 0, 0)
End Select
You can have a string of If statements so multiple actions can occur on a single row:
If DateAdd("m", 1, .Cells(RowCrnt,ColDate).Value) < Now() And _
.Cells(RowCrnt,ColAmtInv).Value) > .Cells(RowCrnt,ColAmtPaid).Value Then
' Invoice overdue
.Rows(RowCrnt).Font.Bold = True
End If
If .Cells(RowCrnt,ColAmtInv).Value) > 5000 Then
' Large invoice
.Rows(RowCrnt).Font.Color = RGB(255, 0, 0)
End If
You do not have to write the entire macro in one go. If most action is because of the product type then try that first.
Hope this helps get you started.

For each cell in a range, if a value in a seperate range is found in the next cell do stuff

This Macro I have built works but I am hoping for a faster version or a Formula that will do the same in less time.
What I Have:
For Each cell In Range("Table_Query_1[[#Data],[Reason2]]")
For Each PossibleValue In Range("F2", Range("F2").End(xlDown))
If Len(cell) = 0 Then
If (InStr(UCase(cell.Offset(0, 1)), UCase(PossibleValue)) <> 0) Then
cell.Value = PossibleValue.Value
End If
Else
Exit For
End If
Next
If Len(cell) = 0 Then
cell.Value = cell.Offset(0, -1)
End If
Next
The only other way I could get anything to work way with the following Array Formula
=IF(ISNA(MATCH($F$3:$F$10,[#Extra Info],0)),[#Reason],$F$3:$F$10)
but this doesn't work for Partial matches as in the case of Row 4 and 9. I also have my doubts that this array formula would be that much faster then a vba macro along with the fact it would also require more upkeep with the test values range (F2:f3) in this case as I would have to constantly update that formula OR I wouild have to make the original range like F2:F100 witch would cause it to take that much longer.
So, what i'd like is if ANY value in my range of values (F2:F3 in this case), Is found inside of the Extra Info Column on the current Row , Then Reason2 of that row (Offset(0, -1)) equals the Value that was matched. But if nothing is found then just use the Reason in that row(Offset(0,1)).
And the second Issue is that I need the Macro to Run After the QueryTable refreshes but if I set it as a Cell Change Event on a cell the is in the query that will change, the macro runs and finishes before the Final querytable is imported and sorted.
Solved!
This is post the comment that I posted above which had the initial formula.
=IF(COUNT(FIND($F$2:$F$3,C1)),"What Will Go Here",A1)
The below tells you what has to go in place of "What Will Go Here"
Put this formula in cell B2. Note that this is an Array Formula. You will have to press CTRL + SHIFT + ENTER after you enter the formula.
=IF(COUNT(FIND($F$2:$F$4,C2)),INDEX($F$2:$F$4,MATCH(SUM(IF(ISNUMBER(--FIND($F$2:$F$4,C2,1)),--FIND($F$2:$F$4,C2,1))),FIND($F$2:$F$4,C2,1),0),0),A2)
Screenshot
Explanation:
FIND($F$2:$F$4,C2,1) when used with an array returns an array. To check the values you can highlight it and press F9 and it will tell you the position at which the match is found. See this screenshot
So it tells us that it found the match at the 3rd position in 4532. It yet doesn't tell us with what did it find a match.
Now the next step is to retrieve the position of that number from the array. So in the above example it will be position 2 and to find that position we will use MATCH() and to use MATCH we will need that 3
So to retrieve 3 from the array we use this formula
=SUM(IF(ISNUMBER(--FIND($F$2:$F$4,C2,1)),--FIND($F$2:$F$4,C2,1)))
Now we have that 3 so we will use it in Match to find the position in the Possible Value
=MATCH(SUM(IF(ISNUMBER(--FIND($F$2:$F$4,C2,1)),--FIND($F$2:$F$4,C2,1))),FIND($F$2:$F$4,C2,1),0)
This will give us 2
Now we know the position of the number in the Possible Value. To find that number we will use INDEX
=INDEX($F$2:$F$4,MATCH(SUM(IF(ISNUMBER(--FIND($F$2:$F$4,C2,1)),--FIND($F$2:$F$4,C2,1))),FIND($F$2:$F$4,C2,1),0),0)
SAMPLE Workbook
http://wikisend.com/download/280280/Sample.xlsx
This is a solution I came across that does not have to be Array Entered and seems to run faster then Siddharth Rout's solution. I am using the formula
=IFERROR(LOOKUP(1E+100,SEARCH($F$2:$F$4,C2),$F$2:$F$4),A2)
Where I am looking for any word in C2 that is in the range F2:F4. If none found it will throw an ERROR and in that situation I know nothing was found and simply return the original reason.
Not shown in the picture I also turn F2:F4 into a named range called Reasons and change the formula too:
=IFERROR(LOOKUP(1E+100,SEARCH(Reasons,C2),Reasons),A2)