Repeat Formula X Times - excel

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

Related

Add columns next to the cell I clicked in before running the macro

I hope everyone is doing well?
I am currently working on an Excel VBA task (my first time working with VBA, so I am sorry if I do ask silly questions). One thing I am researching for almost 2 days now and I can't find a solution anywhere is how to add columns in an Excel sheet via VBA.
To be more precisely: I don't want to add columns in one specific position (e.g. "A:B") but rather to click in a cell, run the macro and it will add 77 columns right next to this cell.
E.g. say I click into cell B2 and run the macro, I would like to have 77 empty columns from column C onwards. I was looking into "ActiveCell" as well but didn't get anywhere.
The macro I found that was the most helpful so far is this:
Sub C_SpaltenEinfügen()
Dim Start As Integer
Start = 2
Range(Cells(1, Start), Cells(1, Start + 77)).EntireColumn.Insert
End Sub
But I am not able to change it from Start = 2 to ActiveCell or anything close to that, so it will only start from column B. As the data set is quite large (currently from Column A to ARW), calculating all starting points wouldn't be very efficent.
I really do appreciate your time and help!
Thanks so much in advance,
Lea
Note that if you want 77 rows added, you would add current through 76 rows, because the first row is the initial insert. This would do that, via double clicking on Row 1:
Option Explicit
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Target.Row = 1 Then
Range(Columns(Target.Column + 1), Columns(Target.Column + 1 + 76)).Insert
Cancel = True
End If
End Sub
You stated that you wanted this to be to the right if where you select, so the .Column+1 offsets the column so you can work with that on the right, e.g., you double click on B1 and you insert 77 columns in front of column C. I left the +1 on the remainder of the range for clarity.
The use of Cancel=True after the insert is so you don't enter the cell you double clicked to begin editing it.
Note where I selected the BeforeDoubleClick... After selecting the sheet module for Sheet1 (Sheet1), I used the drop downs, select Worksheet in the left, then the right I selected BeforeDoubleClick:

How can I calculate the sum of the numbers of two columns for only a portion of the rows?

Say I have an Excel sheet with 10,000 rows and two columns. All 20,000 cells are filled with numbers and there is no missing data. I want to have a third column, the values of which are the sum of Column A and Column B. For example, C70 = A70 + B70, and C82 = A82 + 82, and the like.
The only problem is I want to do it for only a portion of the rows, say from row 125 to row 8954. I don't care about the rest of the values. And I don't want to do it by dragging the grid using the mouse. Is that possible?
If you have access to SEQUENCE() (Currently only available to Office 365 Insiders) then yes it is possible:
=INDEX(A:A,SEQUENCE(1000,,ROW(),1))+INDEX(B:B,SEQUENCE(1000,,ROW(),1))
Where 1000 is the number of rows desired. Place the formula in the first cell desired and it will automatically fill the rest.
I believe you need some logic about what is going on, related to the start and end row.
You can use an if-statement or sumifs() for this... will do an if-statement so i can specify not meeting the requirements as null.
With Start row as 2 and end row as 4 (see image), you can use this formula, and drag it down to the bottom of all columns:
=IF(AND(ROW(A2)<=F$2,ROW(A2)>=E$2),SUM(A2:B2),"")
Notice in the image that C5 has no value; this is due to the conditions of the if-statement being false.
Another idea, a simple macro that will do what you want by asking the user what the starting and end row is.
Sub test()
Dim startrow As Integer 'variable to hold first row
Dim endrow As Integer 'variable to hold last row
startrow = InputBox("Enter the start row")
endrow = InputBox("Enter the end row")
'loops through you desired range calculating what you want
Dim i As Integer
For i = startrow To endrow
Cells(i, 4).Value = Cells(i, 1).Value + Cells(i, 2).Value
Next
End Sub
Just change the values to suit your needs in what cells you want to add up and where you want the sum to go.

Copy cell range and paste in another worksheet based on the date?

I've scoured the interwebs for any kind of solution and I keep coming up empty so hopefully someone can help me out. I have two sheets, Sheet1 and Inventory. In Sheet1, the user enters the date in B1. In range C4:C200 I have a list of supplies and in range D4:D200 a user enters the number of each of the supplies on hand. In Inventory, the list of supplies is in range A1:A200, and b1:z1 list dates.
I'm trying to create a macro that will look in Sheet1 for the date entered in B1, let's say 4/1/19, copy D4:D200, then look in Inventory, find 4/1/19 in rows b1:z1 and paste the copied data beneath the correct date. So if 4/1/19 is in cell E1, the values would be pasted in E2.
While I'm decent with cell formulas and functions, I'm new to macros, so I'm not sure what to do.. Any help is greatly appreciated!
I tried to write some very basic code in such way you can easily read it. It is not the most sophisticated code but it will do the job. Just a few things i noticed: The number of supplies are in a list 197 long, the sheet Inventory states lists of 200 items...well, you can easily adjust the macro below. Copy past the code in a new module and run it. If you encounter any problems please post the complete workbook and i will have a look. Make sure that cell a1 on inventory is not empty.
Sub DoYourThing()
Dim c As Integer
c = findHorizontal("Inventory", 1, Sheets("Sheet1").Cells(1, 2).Value)
'now we know what column the date is in
For i = 2 To 200
Sheets("Inventory").Cells(i, c) = Sheets("Sheet1").Cells(i + 2, 5)
Next i
End Sub
Function findHorizontal(Sheet As String, row As Integer, Value As Variant) As Integer
'searches a row from left to right until the cells are empty
Dim i As Integer
i = 1
Do While Not IsEmpty(Sheets(Sheet).Cells(row, i))
If Sheets(Sheet).Cells(row, i) = Value Then
findHorizontal = i
Exit Function
End If
i = i + 1
Loop
findHorizontal = -1
End Function

Record a variation of a cell - 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

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