Merging 2 cells where cell numbers are variable - vba

I have to merge 2 cells where the range might vary at every run. I am trying with the below code, but there is some error with the code, which I am not able to identify. For fixed range its working fine, but for variable it is showing error. Line no is the cell number which needs to be merged, and it will vary at every run:
Range("D" & line_no & ":" "E" & line_no & ).Select
Range("D" & line_no).Activate
With Selection
.VerticalAlignment = xlCenter
.HorizontalAlignment = xlCenter
.WrapText = False
.Orientation = 0
.AddIndent = False
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = True
End With

I would try to get rid of the Select in general. You could do it like this:
With Range("D" & line_no & ":" & "E" & line_no)
.VerticalAlignment = xlCenter
.HorizontalAlignment = xlCenter
.WrapText = False
.Orientation = 0
.AddIndent = False
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = True
End With

Your problem lies in string concatenation. Comments cover that part.
If this range would be used throughout the program, I'd recommend stroing this range in variable:
define string which will point desired range: Dim rng As String: rng = "D" & line_no & ":E" & line_no, then use it like this:
Range(rng).Select
Range(rng).Activate
OR
define range and store range in the variable instead of a string"
Dim rng As Range
Set rng = Range("D" & line_no & ":E" & line_no)
rng.Select
rng.Activate
'...

Related

How to put line break in Concat fuction in VBA

I have very specific issue, I am trying to concat values to string using line break, I tried all possibilities, nothing works. I tried vbnewline, vbLf, CHR(10).
Range("M2:M" & AfterDuplastRow).Select
With Selection
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.WrapText = True
.Orientation = 0
.AddIndent = False
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End With
Range("M1").Select
ActiveCell.Offset(1, 0).Select
ActiveCell.Formula = _
"=IF(F2=""" & meal & """," & _
"IF(F1<>F2,B2,Concat(M1,CHR(10),B2)),"""")"
also I tried like this
ActiveCell.Formula = _
"=IF(F2=""" & meal & """," & _
"IF(F1<>F2,B2,Concat(M1," & CHR(10) & ",B2)),"""")"
Thank you for your help
Use constant vbNewLine:
ActiveCell.Formula = "=IF(F2=""" & meal & """,IF(F1<>F2,B2,Concat(M1," & vbNewLine & ",B2)),"""")"
This sounds like it may be an XY Problem...
Even if you include a New Line (vbNewLine), a Carriage Return (vbCr), a Line Feed (vbLf), or a Carriage Return and a Line Feed (vbCrLf), it will only be visible in a cell if Wrap Text is turned on for that cell.
As such, try this simple change:
Range("M2:M" & AfterDuplastRow).Select
With Selection
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.WrapText = True
.Orientation = 0
.AddIndent = False
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End With
Range("M1").Select
ActiveCell.Offset(1, 0).Select
ActiveCell.Formula = "=IF(F2=""" & meal & """," & _
"IF(F1<>F2,B2,Concat(M1,CHR(10),B2)),"""")"
Range("M1").WrapText = True 'This line should fix your issue
(Also, you may want to read up on How to avoid using Select in Excel VBA)

Unmerge and paste cells down with vba

I am facing the problem to proecess a report I got into a useful structured excel model.
My problem is that cells in this report are merged and now I would like to unmerge them to process the information much easier.
I tried to record something using the macro recorder, but I am unsure how to automate it on every cell in the sheet.
I would like to let the output look like that:
This is the part I recorded:
Sub Macro1()
Range("A2:A3").Select
With Selection
.HorizontalAlignment = xlGeneral
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = True
End With
Selection.UnMerge
Range("A2").Select
Selection.AutoFill Destination:=Range("A2:A3")
Range("A2:A3").Select
End Sub
Any suggestions how to rewrite this macro to do the merging and pasting automatically?
Appreciate your replies!
UPDATE
I tried to use the selection, however, I am currently facing the problem of not knowing how to get next cell:
Sub split()
'
'Dim C As Double
'Dim R As Double
Dim Rng As Range
'select cells
Set Rng = Selection
'C = Rng
'R = 10
For Each cell In Rng
'starts in row 2 and A -> cell 2,1 is the first cell or A2
cell.Select
With Selection
.HorizontalAlignment = xlGeneral
.VerticalAlignment = xlBottom
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = True
End With
Selection.UnMerge
'Cells(R + 1, C) = Cells(R, C)
If cell.Value = "" Then MsgBox ("Finished splitting and copying!"): End
' If C = 7 Then C = 0: R = R + 2
Next cell
End Sub
Sub Macro1()
NbRows = Sheets("Feuil1").UsedRange.Rows.Count - 1
NbCols = 9 ' If it doesn't change
Range("A2:I11").Copy Destination:= _
Range("K2")
Range("K:S").MergeCells = False ' remove merge
For i = 2 To NbRows ' Number of rows
For j = 11 To NbCols + NbCols ' Number of cols
If Cells(i, j) = "" Then
Cells(i, j) = Cells(i - 1, j).Value
End If
Next j
Next i
End Sub
My code copy-paste the datas from the first table to the cell "K2" (as in your example). Then, you remove the merge that will left some blanks. What you want to do is if cells(i , 1) is empty, then you just use the data from above (cells(i-1, 1))
if the data you want to change is on columns a to g and your are starting from row 2 and assuming all of the cell are not empty
try this code:
Sub split()
'
Dim C As Double
Dim R As Double
C = 1
R = 2
For C = 1 To 7
Cells(R, C).Select
With Selection
.HorizontalAlignment = xlGeneral
.VerticalAlignment = xlBottom
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = True
End With
Selection.UnMerge
Cells(R + 1, C) = Cells(R, C)
If Cells(R, C).Value = "" Then MsgBox ("PROJECT ENDED"): End
If C = 7 Then C = 0: R = R + 2
Next C
End Sub
Please save your data before running the macro. You cannot undo.

Merge cells in different ranges

I have the following:
I expect the following:
I am using this code:
Sub merge_cells()
Application.DisplayAlerts = False
Dim r As Integer
Dim mRng As Range
Dim rngArray(1 To 4) As Range
r = Range("A65536").End(xlUp).Row
For myRow = r To 2 Step -1
If Range("A" & myRow).Value = Range("A" & (myRow - 1)).Value Then
For cRow = (myRow - 1) To 1 Step -1
If Range("A" & myRow).Value <> Range("A" & cRow).Value Then
Set rngArray(1) = Range("A" & myRow & ":A" & (cRow + 0))
Set rngArray(2) = Range("B" & myRow & ":B" & (cRow + 0))
Set rngArray(3) = Range("C" & myRow & ":C" & (cRow + 0))
Set rngArray(4) = Range("D" & myRow & ":D" & (cRow + 0))
For i = 1 To 4
Set mRng = rngArray(i)
mRng.Merge
With mRng
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.WrapText = False
.Orientation = 90
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = True
End With
Next i
myRow = cRow + 2
Exit For
End If
Next cRow
End If
Next myRow
Application.DisplayAlerts = True
End Sub
what I get is:
Question: how to achieve this?
Actually in my original data, the first three columns have data every 88 rows starting from row 3 and the column D should get merged every four rows.
Your code does not distinguish between the different columns in any way. If you know how many rows to merge you can simply search for cells and then do the merge based on column number. Here is one such approach which uses a pair of arrays to track how many rows to merge and then what formatting to apply.
You will need to change the row counts in the array definition. Sounds like you want (87,87,87,3) based on your edit. I did (11,11,11,3) to match your example though. This is the real fix to your code; it uses the Column number to determine how many rows to merge.
I also just typed some values into the spreadsheet and used SpecialCells to get only the cells with values. If your data matches your example, this works fine.
Edit includes unmerging cells first per OP request.
Sub MergeAllBasedOnColumn()
Dim rng_cell As Range
Dim arr_rows As Variant
Dim arr_vert_format As Variant
'change these to the actual number of rows
'one number for each column A, B, C, D
arr_rows = Array(11, 11, 11, 3)
'change these if the formatting is different than example
arr_vert_format = Array(True, True, True, False)
'unmerge previously merged cells
Cells.UnMerge
'get the range of all cells, mine are all values
For Each rng_cell In Range("A:D").SpecialCells(xlCellTypeConstants)
'ignore the header row
If rng_cell.Row > 2 Then
'use column to get offset count
Dim rng_merge As Range
Set rng_merge = Range(rng_cell, rng_cell.Offset(arr_rows(rng_cell.Column - 1)))
'merge cells
rng_merge.Merge
'apply formatting
If arr_vert_format(rng_cell.Column - 1) Then
'format for the rotated text (columns A:C)
With rng_merge
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.WrapText = False
.Orientation = 90
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
End With
Else
'format for the other cells (column D)
With rng_merge
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.WrapText = False
End With
End If
End If
Next rng_cell
End Sub
Before
After

VBA - Invalid Procedure when Creating Pivot Tables within a Loop

All,
I call this subfunction within a loop in another subfunction. The loop works well without this sub called. When I call this sub, it works fine once, and then, on the second go, I get a "runtime error 5 - invalid procedure call or argument" here.
I have many sheets, each with a table. I want to summarize each table with a pivot table.
ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
tblnm, Version:=xlPivotTableVersion10).CreatePivotTable _
TableDestination:=dest, TableName:=pivnm, _
DefaultVersion:=xlPivotTableVersion10
You can see the whole subfunction below.
Sub PIVOT()
Dim pivnm, shtnm, tblnm, dest As String
Application.EnableEvents = False
shtnm = ActiveSheet.Name
tblnm = Range("N2").Value 'I have previously sent the table name to this cell
pivnm = tblnm & " PIVOT"
tblnm = Replace(tblnm, " ", "_")
'The tables are named with underscores, but were stored with spaces
Range("N3") = pivnm
With Range("N3") 'simply wraps the text in the cell
.HorizontalAlignment = xlGeneral
.VerticalAlignment = xlBottom
.WrapText = True
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End With
dest = shtnm & "!R1C15" 'sets the destination
Sheets(shtnm).Select
Range("C1").Select
'the following was written using the macro recorder, with names replaced by
'variables
ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
tblnm, Version:=xlPivotTableVersion10).CreatePivotTable _
TableDestination:=dest, TableName:=pivnm, _
DefaultVersion:=xlPivotTableVersion10
Sheets(shtnm).Select
Cells(1, 15).Select
With ActiveSheet.PivotTables(pivnm).PivotFields("Process text")
.Orientation = xlRowField
.Position = 1
End With
ActiveSheet.PivotTables(pivnm).AddDataField ActiveSheet.PivotTables( _
pivnm).PivotFields("Process text"), "Count of Process text", xlCount
ActiveSheet.PivotTables(pivnm).AddDataField ActiveSheet.PivotTables( _
pivnm).PivotFields("Column1"), "Sum of Column1", xlSum
With ActiveSheet.PivotTables(pivnm).DataPivotField
.Orientation = xlColumnField
.Position = 1
End With
With ActiveSheet.PivotTables(pivnm).PivotFields("Process text")
.Orientation = xlRowField
.Position = 1
End With
shtnm = vbNullString 'I tried resetting everything. Didn't work
tblnm = vbNullString
pivnm = vbNullString
dest = vbNullString
End Sub
Please let me know if I have left any information out or if there is anything I can do better!
I was asked to attach the loop from the other function - so here it is...It probably looks ridiculous to anyone but me...
While count3 <= count2
DoEvents
Application.StatusBar = "Updating. Sheet " & (count3) & " of 61 complete."
Sheets("Sheet2").Select
Selection.AutoFilter Field:=2
Selection.AutoFilter Field:=2, Criteria1:=Range("O" & CStr(count3)).Value
Range("A1:M" & CStr(count)).Select
Selection.Copy
Sheets.Add After:=Sheets(Sheets.count)
ActiveSheet.Paste
If Range("B2") <> "" Then
ActiveSheet.Name = Range("B2")
tblnm = Range("B2").Value
Sheets(tblnm).Select
Application.StatusBar = "Making Table" & (count3) & " of 61 complete."
While Range("B" & CStr(count4 + 1)) <> ""
count4 = count4 + 1
Wend
Range("N1").Value = count4
DataArea = ("$A$1:$M$" & count4)
DataArea1 = DataArea
ActiveWorkbook.ActiveSheet.ListObjects.Add(xlSrcRange, Range(DataArea1), , xlYes).Name = _
tblnm
ActiveWorkbook.ActiveSheet.ListObjects(tblnm).Range.AutoFilter Field:=5, Criteria1:= _
"=*UF_*", Operator:=xlAnd, Criteria2:="<>*Drive*"
ActiveSheet.ListObjects(tblnm).Range.AutoFilter Field:=8, Criteria1:= _
"<>#VALUE!", Operator:=xlAnd
ActiveWorkbook.Worksheets(tblnm).ListObjects(tblnm).Sort.SortFields.Add Key _
:=Range("M1:M" & CStr(count4)), SortOn:=xlSortOnValues, Order:=xlDescending, _
DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets(tblnm).ListObjects(tblnm).Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Call RhidRow
Columns("A:A").EntireColumn.Hidden = True
Columns("B:B").EntireColumn.Hidden = True
Columns("F:F").EntireColumn.Hidden = True
Columns("G:G").EntireColumn.Hidden = True
Columns("H:H").EntireColumn.Hidden = True
Columns("I:I").EntireColumn.Hidden = True
Columns("J:J").EntireColumn.Hidden = True
Columns("K:K").EntireColumn.Hidden = True
Columns("L:L").EntireColumn.Hidden = True
Columns("C:C").EntireColumn.AutoFit
Columns("D:D").EntireColumn.AutoFit
Columns("E:E").EntireColumn.AutoFit
Columns("M:M").EntireColumn.AutoFit
While Range("M" & CStr(count5 + 1)) <> ""
count5 = count5 + 1
Wend
Range("N2") = tblnm
With Range("N2")
.HorizontalAlignment = xlGeneral
.VerticalAlignment = xlBottom
.WrapText = True
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End With
Call PIVOT
Else
ActiveSheet.Delete
End If
Range("A1").Select
count3 = count3 + 1
count4 = 2
count6 = 2
Wend
If your sheet names have spaces in them, you need:
dest = "'" & shtnm & "'!R1C15"
This is untested, but as an idea as to passing parameters:
Sub PIVOT(tblnm As String, ws As Worksheet)
Dim pivnm As String
Dim shtnm As String
Dim dest As String
Dim PT As PivotTable
Application.EnableEvents = False
With ws
shtnm = "'" & .Name & "'"
pivnm = tblnm & " PIVOT"
tblnm = Replace(tblnm, " ", "_")
'The tables are named with underscores, but were stored with spaces
With .Range("N3")
.Value = pivnm
'simply wraps the text in the cell
.HorizontalAlignment = xlGeneral
.VerticalAlignment = xlBottom
.WrapText = True
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End With
End With
dest = shtnm & "!R1C15" 'sets the destination
'the following was written using the macro recorder, with names replaced by
'variables
Set PT = ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
tblnm, Version:=xlPivotTableVersion10).CreatePivotTable( _
TableDestination:=dest, TableName:=pivnm, _
DefaultVersion:=xlPivotTableVersion10)
With PT
With .PivotFields("Process text")
.Orientation = xlRowField
.Position = 1
End With
.AddDataField .PivotFields("Process text"), "Count of Process text", xlCount
.AddDataField .PivotFields("Column1"), "Sum of Column1", xlSum
With .DataPivotField
.Orientation = xlColumnField
.Position = 1
End With
With .PivotFields("Process text")
.Orientation = xlRowField
.Position = 1
End With
End With
End Sub
and the calling code would use something like:
Call PIVOT(tblnm, wks)
where wks is a Worksheet variable set to whichever sheet has the data.

Range in Excel VBA

I have written this code to merge a few lines in each column, from column C to AZ.
For some reason the range does not match the one I was expecting, in this case the code merges the cells C8:C10 then D8:D12, E8:E12, and so on. lines = 2 in this example.
I don't understand why aren't the ranges matching if lines value is not changing inside the for.
Thanks!
For columns = 0 To 49
Range(Range("C8").Offset(0, columns), Range("C8").Offset((lines), columns)).Select
With Selection
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.WrapText = False
.Orientation = 90
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = True
End With
next comlumns
Columns is a reserved word. And you said that this code did run?
If I change that to a valid variable then the code runs. The problem is the way you are using Offset
?[C8].offset(2).address after the way you merge will give you $C$12
Also avoid the use of .Select INTERESTING READ And not to mention fully qualify your objects. For example your range and cell objects are not fully qualified and may give you error.
I think, this is what you are trying to achieve?
Sub Sample()
Dim ws As Worksheet
Dim rng As Range
Dim i As Long, rw As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
rw = 2
With ws
For i = 3 To 52
Set rng = .Range(.Cells(8, i), .Cells(8 + rw, i))
With rng
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.WrapText = False
.Orientation = 90
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = True
End With
Next i
End With
End Sub