Record a variation of a cell - excel - excel

my problem is:
I have a matrix in excel then a function (repeated N times) that extract from this matrix a random number.
This happen everytime i hit F9 or everytime something change in the sheet.
After this i have another cell with a sum of all then numbers extracted. I would like to keep track of the change of this last cell in a linear chart to see how it goes on.
Thank you so much in advance

Solution 1: formulas
if you want to repeat T times, just instead of only 1 series of N number create a matrix of N by T. Then ad 1 last row (or column) under (or next to) the N functions for all T which contains the sum.
Now relate a chart to this last row (or column).
Solution 2: VBA
Create a piece of code that loops T times and copies the value of the cell with the sum into the next empty cell in a designate part of your excel workbook.
Sub aaa
dim i as Long
dim T as Long
T = 1000
For i = 1 to T
Range("rSum").Copy
Cells(rows.count,1).offset(xlUp)).Offset(1, 0).PasteSpecial Paste:=xlPasteValues
Next i
End Sub

Related

VBA Need to sum cells above with inconsistent row numbers

Relatively new to VBA and I have a specific scenario that I need help with. I track daily production numbers for my company and, at the end of each "run" of a product, I have various totals and averages I need to calculate. The issue I'm encountering is that each run is broken out into daily performance and not all runs are the same amount of days.
Here is an example of the layout:
Example Layout
The green row is the total row. Order, Product, and Description are all just equal to the cell above. The rest are sums of the above cells AFTER the last total row.
So far, I got it to insert a row where the active cell is, copy the order, product, and description cells. I also wrote a section to count the number of active days and store it as an integer, "ncount", using CountIf based on the order number, since those are unique to each run. Here is what I have so far:
Sub Total()
' Inserts row and sets color
ActiveCell.EntireRow.Insert
ActiveCell.EntireRow.Interior.ColorIndex = 43
' Sets Order number value
ActiveCell.Value = ActiveCell.Offset(-1)
' Count number of active days
Dim nCount As Integer
Dim order As Long
order = ActiveCell.Value
nCount = Application.WorksheetFunction.CountIf(Range("D:D"), order) - 1
'Sets Product value
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = ActiveCell.Offset(-1)
End Sub
I'm sure that's not the most efficient way to go about those tasks, but I'm still new to VBA and am open to feedback.
What I'm running into is how to successfully sum a range based on the active cell and a count of days running (nCount). I'm thinking I could store the order number as a variable and use it in SumIf statements, but I'm not sure how to do that without the SumIf cell referencing itself.
Can anyone offer some insight?
Thanks!

Column referencing in VBA using sheet().Range().Value

I'm trying to avoid copy and paste in order to dramatically speed up a Macro (previously taking two minutes to run). I am trying to reference four entire columns in Sheetx(A,B,J,L) and have them display in sheety(A6,B6,C6,D6).
I have tried a number of variations of
Sheets("Sheety").Range("A6:A,B6:B,C6:C, D6:D").Value = Sheets("Sheetx").Range("A:A, B:B, J:J, L:L").Value
Also, for sheets("sheety") I tend towards Active.Sheet or Sheets(B) as I have used the index number for the sheet ie
For B = 31
31 being the index number for the real sheet.
I have been searching for answers for the last hour. Can anyone help?
Tell me if something like this:
Sub Testy3()
Dim N As Long
N = Sheets("Sheet1").Cells(Rows.Count, "A").End(xlUp).Row
Sheets("Sheet1").Range("A1:A" & N).Copy Sheets("Sheet2").Range("A6")
End Sub
works for you.
If all the columns in Sheet1 have the same number of rows, then you don't need to re-calculate N for each column.

Repeat Formula X Times

I want to create a VB Script in Excel to populate a row of cells with a specific script but only one of those cells needs to increase by 1.
In Cell A2
=IF(Data!B37="","",Data!B37)
In Cell A3
=IF(Data!B38="","",Data!B38)
The rest of the cells on this tab are fixed formulas as long as something is in the A cell on that row.
=IF(A2="","",IF(Data!$B$5="","",Data!$B$5))
I can use the Record Macro and apply it to a button but is there a way to allow a user to choose how many times to repeat this code down?
In other words, I can record a macro keying in the cell by cell and I can apply that to a button. That's the easy part. I need to be able to allow the user to key in a number of rows needed like "10" in some cell and it repeats the script 10 times down starting on A2 thru I2 which counts for 1, then row 2 starting on A3 thru I3 counts for 2, etc. If not, I could deal with having them click the button 10 times if that makes it easier.
Ultimately, I'm trying to get around the Excel workbook printing the blank cells with formulas with no values. Currently, it says there are 70 pages for something that has 4 pages. I think this will help.
Much appreciated!
Update: (Figured out how to make a cell with a variable in VB Script)
Private Sub CommandButton1_Click()
Dim c As Integer, i As Integer, j As Integer
For c = 5 To 5
For i = 2 To ActiveCell.Value
For j = 1 To 2
Worksheets(c).Cells(i, j).Value = 100
Next j
Next i
Next c
End Sub

How to retrieve value from a list and update in a matrix using excel

I developed a vegetation model in excel and need to add a grazing function.
I have several matrix which do all the calculations for the vegetation components, and now I have a list of steps (random cells visited, 750 out of 2500) and how much biomass was taken from that specific cell.
I need to update each cell value from that list into matrix format again, to calculate the remaining biomass. I've tried several combinations of "index" and "match" and lookups, but could not make it work.
I even numbered all 2500 cells for making it more simple, instead of using row and column reference. Any clue?? (would be the oposit of retrieving a value from a matrix using function Index)
I have something that I think will work for you. I created 3 worksheets. They are named VegMatrix, VisitedCells, and VegMatrixNew.
VegMatrix is the starting matrix and I assumed it was a 50 x 50 with the first data cell in A1. Here is a partial picture:
The next sheet is CellsVisited. It has the rows, cols and the amout of vegetation removed from the cell.
The third sheet is named VegMatrixNew. This is what the original matrix will look like after the removal occurs.
This is done using these VBA macros: They will copy the starting VegMatrix data over to the VegMatrixNew sheet. Then it will loop through the rows in the CellsVisited sheet and get the row, column and amount removed for each cell. The amount removed is subtracted from corresponding cell in VegMatrixNew.
Sub VegRemove()
Dim Wbk As Workbook
Set Wbk = ActiveWorkbook
Dim row As Integer
Dim col As Integer
Dim vegRemoved As Integer
Dim numRows As Integer
CopySheet
Worksheets("VisitedCells").Activate
numRows = Wbk.Worksheets("VisitedCells").Range("A2", Range("A2").End(xlDown)).Rows.Count
For x = 2 To numRows + 1 'start at 2 because of header.
row = Worksheets("VisitedCells").Cells(x, 1).Value
col = Worksheets("VisitedCells").Cells(x, 2).Value
vegRemoved = Worksheets("VisitedCells").Cells(x, 3).Value
Worksheets("VegMatrixNew").Cells(row, col).Value = Worksheets("VegMatrix").Cells(row, col).Value - vegRemoved
Next x
End Sub
Sub CopySheet()
Sheets("VegMatrix").Select
Cells.Select
Selection.Copy
Sheets("VegMatrixNew").Select
Range("A1").Select
ActiveSheet.Paste
Application.CutCopyMode = False
Range("A1").Select
End Sub
I just found a little easier way to do that:
I built a matrix with cell references (which correspond to the original vegetation matrix)
Harvested and corresponding reference table
Then I randomly generated the amount harvested from each cell. The "Reference" uses "index" function to search for the values of X (row) and Y (column) and gives the "cell name" for those specific coordinates.
Reference matrix
On another matrix, I have a if.error function followed by a value lookup
=IFERROR(VLOOKUP("Reference matrix","Reference --> Amount harvested",2,FALSE),0)
Now I can use this lates table to subtract from the original vegetation matrix.
(sorry I could not make this more clear but SO is keeping me from embeding tables and from posting more than two picture links).
Here is the last table that I could not post before:
Updated harvested matrix
The "IFERROR" places "0" where there is no information from the harvested list (cells not harvested)

Removing duplicates from large sheet

I want to remove rows based on duplicate cells in a column from large sheet, without leaving duplicate sample (like "Remove Duplicates" Excel command does). So if I have:
1
2
2
3
I want, as a result:
1
3
This can be accomplished with conditional formatting, then filtering or sorting duplicates and deleting filtered data, but the process is very slow for large sheet.
Conditional formatting takes second, but just clicking on filter takes around 5min to display filter context menu and additional 20-30min to do actual filtering based on color. I tried this process on a different PCs with 4 cores and plenty of RAM and 100.000 rows sheet
I then thought to write VBA, iterate column cells and if cell is colored, then delete entire row (this is possible in Excel 2010, with Cells().DisplayFormat) but processing takes even more time.
Can someone suggest a faster way to remove duplicates on large sheet?
EDIT: Note that I have used 2 functions. Of this, test is a function to test whether the function works (which you will have to modify per your scenario).
Also, I filled cell A1 to A100000 with test values. Please modify it per your needs.
Option Explicit
Function GetUniqueItems(ByVal src As Range) As Variant
Dim returnValue
Dim dictOfItemsWith1Value
Dim dictOfItemsWithMoreThan1Value
Dim countOfCells As Long
Dim counter As Long
Dim srcValues As Variant
Dim currentValue
Dim cell As Range
srcValues = src.Value
countOfCells = src.Cells.Count
Set dictOfItemsWith1Value = CreateObject("Scripting.Dictionary")
Set dictOfItemsWithMoreThan1Value = CreateObject("Scripting.Dictionary")
For counter = 1 To countOfCells
currentValue = srcValues(counter, 1)
If dictOfItemsWithMoreThan1Value.exists(currentValue) Then
dictOfItemsWithMoreThan1Value(currentValue) = dictOfItemsWithMoreThan1Value(currentValue) + 1
Else
If Not dictOfItemsWith1Value.exists(currentValue) Then
dictOfItemsWith1Value.Add currentValue, 1
Else
dictOfItemsWith1Value.Remove currentValue
dictOfItemsWithMoreThan1Value.Add currentValue, 1
End If
End If
Next
ReDim returnValue(1 To dictOfItemsWith1Value.Count, 1 To 1)
Dim key
counter = 1
For Each key In dictOfItemsWith1Value.keys
returnValue(counter, 1) = key
counter = counter + 1
Next
GetUniqueItems = returnValue
End Function
Sub test()
Debug.Print Now
Dim uniqueValues
uniqueValues = GetUniqueItems(Range("A1:A100000"))
Range("A1:A100000").ClearContents
Range("A1").Resize(UBound(uniqueValues, 1)) = uniqueValues
Debug.Print Now
End Sub
My way to deal with large excel files where I have to remove large chunks of data:
After the last column, use a countif() (much like KazJaw and DanM's countif)
=COUNTIF($A$1:$A$100000,A1)
$A$1:$A$100000 contains your ids. Change accordingly.
Drag the formula to the bottom (Fill Down, or select the range $B$1:$B$100000 if this is the column you put the helper column then Ctrl+D)
Copy column and paste values in place to remove the formula. This will prevent any recalculations during/after any filtering.
Sort by the column with the counts. This makes deleting the large portion of rows much faster later on.
Look for where you start to get counts of 2 and delete all rows till bottom.
Delete the helper column.
Now, if you want to restore the original order, put yet another column after the count, after step 3 above, and after step 5, sort this new column by ascending order before deleting it in step 6.
If you data is in located in column A, this formula should do what you need fairly efficiently:
=COUNTIF(A$1:A$100000,A1)
This formula counts how many times the value in A1 appears in the range A1:A100000. (The dollar signs keep that range from moving down as your drag your formula down.)
Place this in B1 and drag down* to B100000 (assuming you have 100,000 rows).
Then just do a filter on column B to show only 1. (More than 1 means you have duplicates and shouldn't show it.)
*A short cut for dragging down is to just select B1, then press Ctrl-End, then hold down shift and click B100000. Then do Ctrl-D (which is a shortcut for Fill Down).

Resources