How to dynamically change range inside formula? - vba

I’m applying a formula:
Textual representation of formula:
=(SUBSTITUTE((LEFT(A2;(FIND("htt";A2;1))-3));";";";"))&RIGHT(A2;(LEN(A2)-(FIND("htt";A2;1))+3))
to all cells in a range A2:A10, writing a result to range B2:B10 respectively.
To do this I use the following macro:
Sub ColumnsFormat()
Dim s As String
Dim i As Integer, j As Integer
'Set wb = Workbooks("CSV_File.xlsm")
Application.ScreenUpdating = False
j = 1
For i = 2 To 10
s = "=(SUBSTITUTE((LEFT(R[" & Trim(Str(i)) & "]C[" & Trim(Str(j - 2)) & "],(FIND(""htt"",R[" & Trim(Str(i)) & "]C[" & Trim(Str(j - 2)) & "],1))-3)),"","","";""))&RIGHT(R[" & Trim(Str(i)) & "]C[" & Trim(Str(j - 2)) & "],(LEN(R[" & Trim(Str(i)) & "]C[" & Trim(Str(j - 2)) & "])-(FIND(""htt"",R[" & Trim(Str(i)) & "]C[" & Trim(Str(j - 2)) & "],1))+3))"
Sheets("Sheet1").Cells(i, 2).Value = s
Next i
End Sub
The problem is that for some reason a row number inside the formula inside a For cycle is wrong. Instead of taking A2; A3; A4 … A10 cells, (changing row number by 1 each time), macro runs through A2; A4; A6 etc. (increasing a row number by 2 each time).
What am I doing wrong?

By changing the row in the formula to 0 the code works just fine. I guess the problem is that in your formula the row was calculated relative to the specific cell the formula was afterwards applied to. Therefore the formula in B2 looked at A(2+2), in B3 at A(3+3) and so on.
Sub ColumnsFormat()
Dim s As String
Dim i As Integer, j As Integer
'Set wb = Workbooks("CSV_File.xlsm")
Application.ScreenUpdating = False
j = 1
For i = 2 To 10
s = "=(SUBSTITUTE((LEFT(R[" & 0 & "]C[" & j - 2 & "],(FIND(""htt"",R[" & 0 & "]C[" & Trim(Str(j - 2)) & "],1))-3)),"","","";""))&RIGHT(R[" & 0 & "]C[" & Trim(Str(j - 2)) & "],(LEN(R[" & 0 & "]C[" & Trim(Str(j - 2)) & "])-(FIND(""htt"",R[" & 0 & "]C[" & Trim(Str(j - 2)) & "],1))+3))"
Sheets("Sheet1").Cells(i, 2).Value = s
Next i
End Sub

Related

Loops and "i" - Correctly inputting "i"

I have no idea how to add in the "i" to the following code. I've gone through previous questions, but I can't get this to run properly. Ideas? Starting after "ELSE", I have no idea how to add in the "i". Any help would be appreciated.
For i = 2 To myLastRow
Set mycell = myWorksheet.Range("AK" & i)
Set mycell2 = myWorksheet.Range("AD" & i)
Else
**mycell.Offset(, 2).Formula = "==IF(ABS(AJ" & i & " - AL" & i & ") <= AL" & i & "*0.1, TRUE, FALSE) "**
Dim i As Integer
Dim mylastrow As Integer
Dim myworksheet As Worksheet
Dim mycell As Range
Dim mycell2 As Range
Set myworksheet = Sheet1
mylastrow = 10
For i = 2 To mylastrow
Cells(i, "AK").Offset(, 2).Formula = "=IF(ABS(AJ" & i & " - AL" & i & ") <= AL" & i & "*0.1, TRUE, FALSE) "
' Cells(i, "AD").Value
Next i
Are you trying to do something like this? The cells property works perfect for thse types of loops.

Updating Alternative text of a button

I have the following code as part of a Job site labor form, which links a full labor call on the "LocLabor" sheet to various single day sign in sheets. This particular code is to add a complete day to the form, and works great, with the exception of these two lines at the bottom:
.Buttons(bnum).ShapeRange.AlternativeText = dayint + 1
.Buttons(bnum + 1).ShapeRange.AlternativeText = dayint + 1
The "scopy", "ecopy", and "brow" variables are used to work out the appropriate lines to copy and paste to the next day. The buttons that are being altered are the newly pasted buttons that were copied within the scopy/ecopy range and are used to add or delete a line from the table they refer to. I need to be able to change the AltText because I am using that as a reference for which day of the labor call they apply to. The "numdays" variable pulls from locsht.Range("L3").Value, which is set to the current number of days on the form prior to running the macro. So it would have a value of 2 when I see the error
Now to the issue - if I have two days existing in the document and I execute the below code, the name of the button changes, but the Alternative Text does not (it remains as "2" or whatever it was prior to copying). Days 4 and up work perfectly though, it is just the transition from day 2 to 3 that I cannot get to work! It also works if I switch out "dayint + 1" to a string, like "banana" for example, but that obviously doesn't help me.
Any ideas would be appreciated.
Option Explicit
Sub add_day()
Dim numdays As String
Dim tbl As TableStyle
Dim newsht As Worksheet
Dim locsht As Worksheet
Dim scopy As Integer
Dim ecopy As Integer
Dim brow As Integer
Dim dayint As Integer
Dim bnum As Integer
Dim tblstart As String
Application.ScreenUpdating = False
'unlock sheet
Worksheets("LocLabor").Unprotect Password:=SuperSecretPW
'set/get variables
Set locsht = Worksheets("LocLabor")
numdays = locsht.Range("L3").Value
dayint = numdays
Worksheets("Labor Sign In Day " & numdays).Copy Before:=Sheets(numdays + 4)
Worksheets("Labor Sign In Day " & numdays & " (2)").Name = "Labor Sign In Day " & numdays + 1
'update number of days on sheet
locsht.Range("L3") = locsht.Range("L3").Value + 1
'rename new sign in sheet
Set newsht = Worksheets("Labor Sign In Day " & numdays + 1)
newsht.Unprotect Password:=SuperSecretPW
'figure out which rows to copy on main sheet
scopy = locsht.ListObjects(dayint).Range.Rows(1).Row - 1
brow = locsht.ListObjects(dayint).Range.Rows.Count
ecopy = scopy + brow
'Copy/paste new day on LocLabor
locsht.Activate
locsht.Rows(scopy & ":" & ecopy).Copy
locsht.Rows(ecopy + 2).Insert Shift:=xlDown
locsht.ListObjects("Tableday" & numdays).Resize Range("A" & scopy + 1 & ":" & "H" & ecopy)
locsht.Range("A" & ecopy + 2 & ":" & "H" & ecopy + 2) = "=IFERROR($A$17+" & numdays & "," & """Enter Load in Date at Top"")"
locsht.Rows(ecopy + 1).EntireRow.Delete
locsht.PageSetup.PrintArea = "$A$1:$H$" & ecopy + (ecopy - scopy + 1)
locsht.HPageBreaks.Add Before:=locsht.Rows(ecopy + 1)
locsht.ListObjects(dayint + 1).Name = "Tableday" & numdays + 1
bnum = (dayint * 2) + 3
tblstart = locsht.ListObjects(dayint + 1).Range.Rows(1).Row + 1
'Enter correct formulas into sign in sheet
With newsht
.ListObjects(1).Name = "signinday" & numdays + 1
.Range("i12") = Left(newsht.Range("i12").Formula, 28) & numdays & Right(newsht.Range("i12").Formula, 48)
.Range("A17") = "=IF(ISBLANK(LocLabor!G" & tblstart & ")=FALSE,LocLabor!G" & tblstart & "&"" ""&LocLabor!F" _
& tblstart & ",IF(ISBLANK(LocLabor!D" & tblstart & ")=TRUE," & """""" & ",LocLabor!D" & tblstart & "))"
.Range("B17") = "=IF(ISBLANK(LocLabor!B" & tblstart & ")=TRUE, """", LocLabor!B" & tblstart & ")"
.Range("G17") = "=IF(ISBLANK(LocLabor!C" & tblstart & ")=TRUE, """", LocLabor!C" & tblstart & ")"
End With
'rename pasted buttons, update alttext
With locsht
.Buttons(bnum).Name = "Button " & bnum
.Buttons(bnum + 1).Name = "Button " & bnum + 1
.Buttons(bnum).ShapeRange.AlternativeText = dayint + 1
.Buttons(bnum + 1).ShapeRange.AlternativeText = dayint + 1
End With
'lock down sheets
Worksheets("LocLabor").Protect Password:=SuperSecretPW, DrawingObjects:=False, Contents:=True, Scenarios:=True _
, AllowFormattingCells:=True, AllowFormattingRows:=True, _
AllowInsertingRows:=True, AllowDeletingRows:=True, AllowSorting:=True, _
AllowFiltering:=True
Worksheets("LocLabor").EnableSelection = xlUnlockedCells
Worksheets("Labor Sign In Day " & numdays + 1).Protect Password:=SuperSecretPW, DrawingObjects:=False, Contents:=True, Scenarios:=True _
, AllowFormattingCells:=True, AllowFormattingRows:=True, _
AllowInsertingRows:=True, AllowDeletingRows:=True, AllowSorting:=True, _
AllowFiltering:=True
Worksheets("Labor Sign In Day " & numdays + 1).EnableSelection = xlUnlockedCells
ActiveSheet.Buttons(Application.Caller).TopLeftCell.Offset(3, 0).Select
Application.ScreenUpdating = True
End Sub

VBA, concact 2 values with the same variable in cell

I'm trying to write a VBA script. This script would read 1 column and write the result in another column.
If the values are in bold or if is not blank, I would like to write the data in the column b1.
But if the values are not in bold, I would like to write the data in c1, and concatenate if I have 2 or more non-bold data in the same cell.
My code :
Sub Phone()
Dim valueLogon As String
Dim ValueDevice As String
Dim compteur As Integer
compteur = 1
For i = 1 To 2101
valueLogon = Range("A" & i)
If Range("A" & i).Font.bold = True And IsEmpty(valueLogon) = False Then
compteur = compteur + 1
Range("C" & i) = valueLogon
Else
Range("D" & compteur) = valueLogon & "," &
End If
Next i
End Sub
now, my result is like to the picture, but I would like concactenate the non-bold result in the same cell
change
Range("D" & compteur) = valueLogon & "," &
to
Range("D" & compteur).Value = valueLogon & "," & Range("D" & comptuer).Value

Incorrect formula result via VBA

I have made a simple program to put a particular formula in Excel. The problem is the occurrence of single inverted quotes in the result.
Where the result should be ='[Fiber Loss Report - 7210 DCN.xlsx]1310'!G9,
the result i get is ='[Fiber Loss Report - 7210 DCN.xlsx]1310'!'G9'
Sub CopyValues()
Dim n As Integer
Dim y As Integer
Dim rng As Range
y = 6
For n = 9 To 175
rngText = "D" & y
Range(rngText).Select
'rng.Select
'Range("D6").Select
formulaText = "='[Fiber Loss Report - 7210 DCN.xlsx]1310'!G" & n
ActiveCell.FormulaR1C1 = formulaText
rngText = "E" & y
Range(rngText).Select
formulaText = "='[Fiber Loss Report - 7210 DCN.xlsx]1310'!G" & n + 1
ActiveCell.FormulaR1C1 = formulaText
n = n + 2
y = y + 1
Next
End Sub
Please let me know on how can I avoid the occurrence of these single quotes.
Further to my comments below your question...
You need to find trends in your code. That ways you can avoid the loops.
For example, your formula from D6 to D61 increase from G9 to G12 to G15 and so on. Similarly for Col E.
So there is a trend. The next question you can ask yourself is "What formula can I write where I can get results like 9, 12, 15, 18 and so on?". The formula is
=(ROW()-3)*3
If you put that formula say in G6 and pull it down, you will get that sequence.
Now also instead of looping we can write formula to the entire range is one go. So we simply combine the above with Indirect. See this
Shortest possible code?
Sub CopyValues()
Dim ws As Worksheet
Dim fName As String
fName = "Fiber Loss Report - 7210 DCN.xlsx"
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
'"='[Fiber Loss Report - 7210 DCN.xlsx]1310'!G9"
.Range("D6:D61").Formula = "=INDIRECT(" & Chr(34) & "'[" & _
fName & "]1310'!G" & Chr(34) & _
" & (ROW()-3)*3)"
.Range("E6:E61").Formula = "=INDIRECT(" & Chr(34) & "'[" & _
fName & "]1310'!G" & Chr(34) & _
" & (ROW()-3)*3+1)"
End With
End Sub
JUST FOR FUN
I can convert the above code in just two lines. Simply replace Sheet1 with the relevant sheet name.
Sub CopyValues()
ThisWorkbook.Sheets("Sheet1").Range("D6:D61").Formula = "=INDIRECT(" & Chr(34) & "'[Fiber Loss Report - 7210 DCN.xlsx]1310'!G" & Chr(34) & " & (ROW()-3)*3)"
ThisWorkbook.Sheets("Sheet1").Range("E6:E61").Formula = "=INDIRECT(" & Chr(34) & "'[Fiber Loss Report - 7210 DCN.xlsx]1310'!G" & Chr(34) & " & (ROW()-3)*3+1)"
End Sub
Option Explicit
Sub CopyValues()
Dim i As Long, j As Long
j = 6
For i = 9 To 175 Step 3
Range("D" & j).Formula = "='[Fiber Loss Report - 7210 DCN.xlsx]1310'!G" & i
Range("E" & j).Formula = "='[Fiber Loss Report - 7210 DCN.xlsx]1310'!G" & i + 1
j = j + 1
Next
End Sub
Result: ='[Fiber Loss Report - 7210 DCN.xlsx]1310'!G9
You can just remove single inverted quotes and change to RC format:
Sub CopyValues()
Dim n As Integer
Dim y As Integer
Dim rng As Range
y = 6
For n = 9 To 175
rngText = "D" & y
Range(rngText).Select
'rng.Select
'Range("D6").Select
formulaText = "=[Fiber Loss Report - 7210 DCN.xlsx]1310!R" & n & "C7"
ActiveCell.FormulaR1C1 = formulaText
rngText = "E" & y
Range(rngText).Select
formulaText = "=[Fiber Loss Report - 7210 DCN.xlsx]1310!R" & n + 1 & "C7"
ActiveCell.FormulaR1C1 = formulaText
n = n + 2
y = y + 1
Next
End Sub
Using .value instead of .FormulaR1C1 solves the problem. :)

How to loop rows with Excel VBA macro?

I am new to VBA, but pretty good with PHP. That being said, I'm struggling with VBA loops...
I have this sheet with 40 rows called "SH1":
SH1
A B C D E
1 2 One 1.0a 12
2 7 Two 2.0b 34
3 13 Three 3.0c 56
4 14 Four 4.0d 78
..
40
I need to loop through 40 rows and check the value in column A. If the value in column A meets my criteria (see below), generate some output and put it in another sheet.
My output sheet is 3-columns and called "SH2":
SH2
A B C D E
1 1.0a 12 One
2.0b 34 Two
2 3.0c 56 Three
4.0d 78 Four
..
15
My criteria for deciding what goes where:
// First loop:
if a1 < 8, put c1 in SH2 a1, put d1 in SH2 b1, put b1 in SH2 c1
if a2 < 8, put c2 in SH2 a1, put d2 in SH2 b1, put b2 in SH2 c1
// ... loop through a40 ...
Then:
// Second loop:
if a1 > 8 AND a1 < 16, put c1 in SH2 a2, put d1 in SH2 b2, put b1 in SH2 c2
if a2 > 8 AND a2 < 16, put c2 in SH2 a2, put d2 in SH2 b2, put b2 in SH2 c2
// ... loop through a40 ...
PROGRESS EDIT:
Seems to be working, but wondering if there is a "cleaner" way?
Sub CatchersPick2()
Dim curCell As Range
For Each curCell In Sheet4.Range("C3:C40").Cells
If curCell.Value > 0 And curCell.Value < 73 Then
cLeft = cLeft _
& curCell.Offset(0, 5) & "." _
& curCell.Offset(0, 6) & vbLf
cMidl = cMidl _
& curCell.Offset(0, -2) & ", " _
& curCell.Offset(0, -1) & " " _
& curCell.Offset(0, 7) & vbLf
cRght = cRght _
& curCell.Offset(0, 9) & " " _
& curCell.Offset(0, 2) & " " _
& curCell.Offset(0, 11) & " " _
& curCell.Offset(0, 10) & vbLf
End If
Next curCell
Sheet6.Range("B3") = cLeft
Sheet6.Range("C3") = cMidl
Sheet6.Range("D3") = cRght
Sheet6.Range("B3:D3").Rows.AutoFit
Sheet6.Range("B3:D3").Columns.AutoFit
End Sub
Dim cell As Range
For Each cell In Range("a1:a40")
'do stuff here
Next cell
You can get your current row with cell.Row. Good luck ^_^
How about:
Sub Catchers()
Dim cell As Range
Sheet1.Select 'SHEET: C
For Each cell In Range("C3:C40")
If cell.Value < 35 And cell.Value > 0 Then
With Sheet6
.Range("B" & cell.Row) = cell.Offset(0, 5) _
& "." & cell.Offset(0, 6)
.Range("C" & cell.Row) = cell.Offset(0, -2) _
& ", " & cell.Offset(0, -1) _
& " " & cell.Offset(0, 7)
.Range("D" & cell.Row) = cell.Offset(0, 9) _
& " " & cell.Offset(0, 2) _
& " " & cell.Offset(0, 11) _
& " " & cell.Offset(0, 10)
End With
End If
Next cell
Sheet6.Range("B4:D4").Rows.AutoFit
Sheet6.Range("B4:D4").Columns.AutoFit
End Sub
There's not a lot you can do, but...
First, don't use the word 'cell' as a variable, it may work, but it's playing with fire, so
Dim curCell as Range
Second, you should loop through the Cells property of the Range
For Each curCell In Range("C3:C40").Cells
Third, you don't need to Select the cell, you can just manipulate the curCell variable
Lastly, you won't need to use ActiveCell, just use the curCell variable.
If curCell.Value < 35 And curCell.Value > 0 Then
cLefta = curCell.Offset(0, 5) & "."
In fact, you could also just use a short variable like 'c' and put the whole thing on one line:
cLeft = c.Offset(0,5) & "." & c.Offset(0,6) & vblf
Note: If your setup is close to the same every time, it would probably be easier to just use worksheet-functions.