Merge Two Columns of Data into a Single Variable - excel

I have a spreadsheet with two columns of data, both columns have a header. I would like to establish a variable for each row of data I can then use to generate new worksheet names and insert into formulas. My variable would be a one to one ratio with the data, meaning A2-B2, A3-B3, etc. I have tried the following code:
'''Sub CreateSheet2()
Dim rngBP As Range
Dim rngCon As Range
Dim cellBP As Range
Dim cellCon As Range
On Error GoTo Errorhandling
Set rngBP = Application.InputBox(prompt:="Bid Package Select Cell Range:", Title:="Create Sheets", Default:=Selection.Address, Type:=8)
Set rngCon = Application.InputBox(prompt:="Contractor Select Cell Range:", Title:="Create Sheets", Default:=Selection.Address, Type:=8)
For Each cellBP In rngBP
If cellBP <> "" And cellCon <> "" Then
Sheets.Add(after:=ActiveWorkbook.Worksheets(ActiveWorkbook.Worksheets.Count)).Name = cellBP & "-" & cellCon
End If
Next cellBP
Errorhandling:
MsgBox prompt:="Error Detected" & vbNewLine & "Error" & Err.Number & ": " & Err.Description
End Sub'''
However, this code generates a variable with all of the possible combinations (A2-B2, A2-B3, A3-B3, etc.). Ideally, this code would also skip empty cells and not create a variable for that entire row. Here is a screenshot of my sample dataset.Sample Dataset. Thank you for the assistance.

Add Worksheets with Names Created from Two Columns
I see the double Application.InputBoxes as a disaster waiting to happen so I abandoned the idea.
The code will search for the specified headers in the first row and their columns will define the column ranges (from the 2nd to the last row).
Copy the code into a standard module, e.g. Module1.
Adjust the four constants.
You only run the first procedure which will call the second when needed.
The third procedure is showing an example of proper error handling. Study it closely.
The Code
Option Explicit
Sub CreateSheet2()
'On Error GoTo ErrorHandling
Const wsName As String = "Sheet1"
Const bTitle As String = "Bid Package"
Const cTitle As String = "Contractor"
Const FirstRow As Long = 2
Dim wb As Workbook
Set wb = ThisWorkbook ' The workbook containing this code.
Dim ws As Worksheet
Set ws = wb.Worksheets(wsName)
Dim bCol As Variant
bCol = Application.Match(bTitle, ws.Rows(1), 0)
Dim cCol As Variant
cCol = Application.Match(cTitle, ws.Rows(1), 0)
Dim LastRow As Long
LastRow = ws.Cells(ws.Rows.Count, bCol).End(xlUp).Row
Dim ColumnOffset As Long
ColumnOffset = cCol - bCol
Dim SheetNames As Variant
SheetNames = getSheetNames(wb)
Dim rng As Range
Set rng = ws.Cells(FirstRow, bCol).Resize(LastRow - FirstRow + 1)
Dim cel As Range
Dim SheetName As String
For Each cel In rng.Cells
If cel.Value <> "" And cel.Offset(, ColumnOffset).Value <> "" Then
SheetName = cel.Value & "-" & cel.Offset(, ColumnOffset).Value
If IsError(Application.Match(SheetName, SheetNames, 0)) Then
On Error Resume Next
wb.Worksheets.Add(After:=wb.Sheets(wb.Sheets.Count)).Name _
= SheetName
If Err Then ' might happen if there are duplicates in columns.
Application.DisplayAlerts = False
ActiveSheet.Delete
Application.DisplayAlerts = True
End If
On Error GoTo ErrorHandling
End If
End If
Next cel
ProcExit:
Exit Sub
ErrorHandling:
MsgBox Prompt:="Error Detected" & vbNewLine & "Error '" & Err.Number _
& "': " & Err.Description, _
Buttons:=vbCritical, _
Title:="Fail"
Resume ProcExit
End Sub
Function getSheetNames(Book As Workbook) _
As Variant
If Book Is Nothing Then
GoTo ProcExit
End If
Dim Data As Variant
ReDim Data(1 To Book.Sheets.Count)
Dim sh As Object
Dim n As Long
For Each sh In Book.Sheets
n = n + 1
Data(n) = sh.Name
Next sh
getSheetNames = Data
ProcExit:
End Function
Proper Error Handling
Sub ProperErrorHandling()
On Error GoTo ErrorHandling
' The code
ProcExit:
Exit Sub ' You don't want to show the message if no error and
' you must not 'Resume' with no error!
ErrorHandling:
MsgBox Prompt:="Error Detected" & vbNewLine & "Error '" & Err.Number _
& "': " & Err.Description, _
Buttons:=vbCritical, _
Title:="Fail"
' Sets the error number to 0, but still keeps the error handler active.
' Therefore be aware that if you put code between 'ProcExit' and 'Exit Sub'
' and an error occurs, it will result in an endless loop.
Resume ProcExit ' 'Resume', not 'GoTo'!
End Sub

Please try this code.
Sub CreateSheet2()
Const BidPack As String = "A" ' specify a column
Const Contractor As String = "B" ' change to suit (to the right of BidPack)
Const FirstDataRow As Long = 2 ' change to suit
Dim Wb As Workbook
Dim Ws As Worksheet
Dim BidRng As Range
Dim ConRng As Range
Dim Tmp As Variant ' misc use
Dim WsName As String
Dim R As Long ' loop counter: rows
Set Wb = ActiveWorkbook ' change to suit
WsName = "Sheet1" ' change to suit
Application.ScreenUpdating = False
Tmp = Columns(Contractor).Column
With Wb.Worksheets(WsName)
Set ConRng = .Range(.Cells(FirstDataRow, Tmp), _
.Cells(.Rows.Count, Tmp).End(xlUp))
' ConRng and BidRng are of identical size,
' not exceeding the number of rows available in ConRng.
Set BidRng = ConRng.Offset(, Columns(BidPack).Column - Tmp)
For R = 1 To BidRng.Cells.Count
If (Not IsEmpty(BidRng.Cells(R))) And (Not IsEmpty(ConRng.Cells(R))) Then
WsName = Format(BidRng.Cells(R).Value, "00-") & ConRng.Cells(R).Value
On Error Resume Next
Set Tmp = Wb.Sheets(WsName)
If Err Then
Wb.Sheets.Add(After:=Wb.Sheets(Wb.Sheets.Count)).Name = WsName
Else
MsgBox "A worksheet by the name of """ & WsName & _
""" already exists.", vbInformation, _
"Duplicate instruction"
End If
End If
Next R
End With
Application.ScreenUpdating = False
End Sub

I think it's best
loop through rngBP range not empty values, only
using a Dictionary object to ensure you're not duplicating sheet names
Option Explicit
Sub CreateSheets()
Dim rngBP As Range
Dim cellBP As Range
On Error GoTo Errorhandling
Set rngBP = Application.InputBox(prompt:="Bid Package Select Cell Range:", Title:="Create Sheets", Default:=Selection.Address, Type:=8)
Dim shNamesDict As Object
Set shNamesDict = CreateObject("Scripting.Dictionary")
With ActiveWorkbook
Dim shName As String
For Each cellBP In rngBP.SpecialCells(xlCellTypeConstants)
If Not IsEmpty(cellBP.Offset(, 1).Value2) Then
shName = cellBP.Value2 & "-" & cellBP.Offset(, 1).Value2
If Not shNamesDict.exists(shName) Then
shNamesDict.Add shName, 0
.Sheets.Add(after:=.Worksheets(.Worksheets.Count)).Name = shName
End If
End If
Next
End With
Errorhandling:
If Err.Number <> 0 Then MsgBox prompt:="Error Detected" & vbNewLine & "Error" & Err.Number & ": " & Err.Description
End Sub

Related

Copy values from multiple sheets to summary sheet

In the image, there are some empty cells in column L,M, W:Z.
I am trying to loop through all sheets in the workbook.
Starting from Sheet1, filter out the empty "L" cells under the blue header in "A7",
copy the array of values (between A:Z or all cells with values in the row, ideally),
paste the copied array in the summary sheet,
Copy P2 for each sheet and paste the value as a separator between sheets.
Then continue a loop through the sheets.
Typically these workbooks have between 100-150 sheets.
These workbooks are generated for work, so I have adjusted the values accordingly.
South Park references everywhere is my style with VBA since nobody else sees them.
Issue: row numbers are dynamic, and I do not know how to offset from row "A7" after filtering without variation.
Sub Missing_L_Value_Summary()
Dim MyRange As Range
Dim MyCell As Range
Dim ws As Worksheet, myValue
Dim lCount As Long
Dim title As Long
Dim rng As Range
Application.ScreenUpdating = False
Application.EnableEvents = False
ActiveSheet.Name = "Sheet1"
'Workbook.Save.Name = Range("A2") & "James Cameron"
'Range("A2").Copy
Sheets.Add.Name = "Summary"
Sheets("Summary").Select
'Range("A1").PasteSpecial
ActiveCell.Offset(2, 1).Select
Sheets("Sheet1").Select
Range("A8").Copy
Sheets("Summary").Select
ActiveCell.PasteSpecial
Range("B3").EntireColumn.AutoFit
Sheets("Sheet1").Select
Range("$A$7:$Z$7").Copy
Sheets("Summary").Select
ActiveCell.Offset(1, 0).PasteSpecial
Sheets("Sheet1").Select
For Each ws In Sheets
Range("L7").Select
With ws.Cells(7, 12).CurrentRegion
.AutoFilter Field:=12, Criteria1:="="'
Application.ScreenUpdating = True
Application.EnableEvents = True
MsgBox("James Cameron doesn't do what James Cameron does for James Cameron. James Cameron does
End Sub
what James Cameron does for James Cameron!")
Get Filtered Rows
Option Explicit
Sub Missing_L_Value_Summary()
Const ProcName As String = "Missing_L_Value_Summary"
On Error GoTo ClearError
Dim IsSuccess As Boolean
Const sExceptionsList As String = "Summary" ' add more
Const sExceptionsDelimiter As String = ","
Const sBeforeSheetName As String = "Sheet1"
Const sfCellAddressCR As String = "L7"
Const sDateAddress As String = "P2"
Const sField As Long = 12
Const sCriteria As String = "="
Const dName As String = "Summary"
Const dfCellAddress As String = "A3"
Const dDateCol As String = "B"
Application.ScreenUpdating = False
Application.EnableEvents = False
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim dws As Worksheet
On Error Resume Next ' prevent error if it doesn't exist
Set dws = wb.Worksheets(dName)
On Error GoTo ClearError
If Not dws Is Nothing Then
Application.DisplayAlerts = False ' delete without confirmation
dws.Delete
Application.DisplayAlerts = True
End If
Set dws = wb.Worksheets.Add(Before:=wb.Worksheets(sBeforeSheetName))
dws.Name = dName
Dim dCell As Range: Set dCell = dws.Range(dfCellAddress)
Dim sExceptions() As String
sExceptions = Split(sExceptionsList, sExceptionsDelimiter)
Dim sws As Worksheet
Dim srg As Range
Dim svrg As Range
Dim drg As Range
Dim dData As Variant
Dim drCount As Long
Dim ErrNum As Long
For Each sws In wb.Worksheets
If IsError(Application.Match(sws.Name, sExceptions, 0)) Then
If sws.AutoFilterMode Then sws.AutoFilterMode = False
' Write date.
dCell.EntireRow.Columns(dDateCol).Value = sws.Range(sDateAddress)
Set dCell = dCell.Offset(1)
' Write data.
Set srg = sws.Range(sfCellAddressCR).CurrentRegion
On Error Resume Next
srg.AutoFilter sField, sCriteria
ErrNum = Err.Number
On Error GoTo ClearError
If ErrNum = 0 Then
On Error Resume Next
Set svrg = srg.SpecialCells(xlCellTypeVisible)
On Error GoTo ClearError
sws.AutoFilterMode = False
If Not svrg Is Nothing Then
dData = GetFilteredRows(svrg)
If Not IsEmpty(dData) Then
drCount = UBound(dData, 1)
Set drg = dCell.Resize(drCount, UBound(dData, 2))
drg.Value = dData
Set dCell = dCell.Offset(drCount)
Set svrg = Nothing
End If
End If
End If
End If
Next sws
IsSuccess = True
SafeExit:
If Application.EnableEvents = False Then
Application.EnableEvents = True
Application.ScreenUpdating = True
End If
If IsSuccess Then
MsgBox "James Cameron doesn't do what James Cameron does " _
& "for James Cameron. James Cameron does what James Cameron does " _
& "for James Cameron!", vbInformation
Else
MsgBox "Something went wrong.", vbCritical
End If
Exit Sub
ClearError:
Debug.Print "'" & ProcName & "': Unexpected Error!" & vbLf _
& " " & "Run-time error '" & Err.Number & "':" & vbLf _
& " " & Err.Description
Resume SafeExit
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Returns the values of a filtered range in a 2D one-based array.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function GetFilteredRows( _
ByVal FilteredRange As Range) _
As Variant
Const ProcName As String = "GetFilteredRows"
On Error GoTo ClearError
Dim saCount, drCount, cCount
With FilteredRange
saCount = .Areas.Count
drCount = Intersect(.Offset(0), _
.Worksheet.Columns(.Cells(1).Column)).Cells.Count
cCount = .Areas(1).Columns.Count
End With
Dim dData As Variant: ReDim dData(1 To drCount, 1 To cCount)
Dim sarg As Range
Dim sData As Variant
Dim srCount As Long, sr As Long, dr As Long, c As Long
For Each sarg In FilteredRange.Areas
srCount = sarg.Rows.Count
If cCount + srCount > 2 Then
sData = sarg.Value
Else
ReDim sData(1 To 1, 1 To 1)
sData(1, 1) = sarg.Value
End If
For sr = 1 To srCount
dr = dr + 1
For c = 1 To cCount
dData(dr, c) = sData(sr, c)
Next c
Next sr
Next sarg
GetFilteredRows = dData
ProcExit:
Exit Function
ClearError:
Debug.Print "'" & ProcName & "': Unexpected Error!" & vbLf _
& " " & "Run-time error '" & Err.Number & "':" & vbLf _
& " " & Err.Description
Resume ProcExit
End Function
i use only offset formula because if i remove lines or columns he never give error
ex: if im in cell B5 of sheet2 and want show same information from sheet1
=OFFSET(sheet1!$A$1;ROW(B5)-1;COLUMN(B5)-1)
Only cell fix are A1 sheet1

Execute Time (Select, Copy & Paste in same order for Non Adjacent Cells)

This VBA takes a lot of time to execute
Sub test()
Dim IB As String
Dim copyRng As Range, cel As Range, pasteRng As Range
With Selection
Set copyRng = Selection
End With
IB = Application.InputBox("Enter Exact Sheet Name to Paste")
Set pasteRng = Sheets(IB).Range("A1")
For Each cel In copyRng
cel.Copy
pasteRng.Range(cel.Address).PasteSpecial xlPasteAll
Next
Application.CutCopyMode = False
End Sub
Copy Non-Contiguous Ranges
I've turned off screen updating and replaced looping through cells with looping through areas of the range.
When you would only need values to be copied, another (vast) improvement in performance would be to copy by assignment. Then in the loop, you would use the following code:
darg.Value = sarg.Value
instead of sarg.Copy darg.
Option Explicit
Sub CopyNonContiguous()
Const ProcTitle As String = "Copy Non-Contiguous"
Dim srg As Range
If TypeName(Selection) = "Range" Then
Set srg = Selection
Else
MsgBox "Select a range. please.", vbCritical, ProcTitle
Exit Sub
End If
Dim wsName As Variant
wsName = Application.InputBox( _
"Enter Sheet Name to Paste", ProcTitle, , , , , , 2)
If wsName = False Then
MsgBox "You canceled.", vbExclamation, ProcTitle
Exit Sub
End If
Dim dws As Worksheet
On Error Resume Next
Set dws = ActiveWorkbook.Worksheets(wsName) ' consider 'ThisWorkbook'
On Error GoTo 0
If dws Is Nothing Then
MsgBox "The worksheet '" & wsName & "' doesn't exist.", _
vbCritical, ProcTitle
Exit Sub
End If
Application.ScreenUpdating = False
Dim sarg As Range
Dim darg As Range
For Each sarg In srg.Areas
Set darg = dws.Range(sarg.Address)
sarg.Copy darg
Next sarg
Application.ScreenUpdating = True
MsgBox "Cells copied.", vbInformation, ProcTitle
End Sub

Object Doesn't Support this Property or Method When copying from another workbook

I'm trying to write a small code in Excel that lets me open in the background another workbook, copy a range of data in there, and then pasty it in the active workboo. Should be pretty straight forward but for some reason I'm getting this error. So far what I've got is this, and I know the error comes from this line "cpyLastRow = ImportBook.cpySheet.Cells(3, 1).End(xlDown).Row", Ive got some variables commented to make it a little bit mor dyanimc in the future. Any ideas?
Private Sub CommandButton2_Click()
Dim OpenFile As Variant
Dim ImportBook As Workbook
Dim cpySheet As Worksheet
Dim cpyLastRow As Long
Dim cpyLastColumn As Long
'Dim cpyStartCell As Range
Set cpySheet = Sheets("DAO")
'Set cpyStartCell = Range("C3")
Application.ScreenUpdating = False
OpenFile = Application.GetOpenFilename(Title:="Select a file to import data", filefilter:="Excel Files (*.xls*),*xls*")
If OpenFile <> False Then
Set ImportBook = Application.Workbooks.Open(OpenFile)
cpyLastRow = ImportBook.cpySheet.Cells(3, 1).End(xlDown).Row
'cpyLastColumn = cpyStartCell.Column
ImportBook.cpySheet.Range("C3", cpySheet.Cells(cpyLastRow, 3)).Copy
ThisWorkbook.ActiveSheet.Range("C3").PasteSpecial xlPasteValues
ImportBook.Close False
End If
Application.ScreenUpdating = True
End Sub
You get an error due to mixing import workbook property and active worbook sheet reference. Try to use method 1 or method 2. Be sure to specify actual sheet name in the import workbook.
'get reference to sheet "ABF - DAO" in active workbook
Set cpySheet = Sheets("ABF - DAO")
...
'error: mix workbook property and sheet reference
cpyLastRow = ImportBook.cpySheet.Cells(3, 1).End(xlDown).Row
'method 1: get reference to sheet in import workbook
Set cpySheet = ImportBook.Sheets("ABF - DAO")
cpyLastRow = cpySheet.Cells(3, 1).End(xlDown).Row
'method 2: get last row without sheet reference
cpyLastRow = ImportBook.Sheets("ABF - DAO")
Copy Column Range From Closed Workbook
Option Explicit
Private Sub CommandButton2_Click()
Const ProcName As String = "CommandButton2_Click"
On Error GoTo clearError
Const sTitle As String = "Select a file to import data"
Const sFilter As String = "Excel Files (*.xls*),*xls*"
Const sName As String = "DAO"
Const sFirst As String = "C3"
Const dFirst As String = "C3"
Dim dSuccess As Boolean
' Source
' Path
Dim sPath As Variant
sPath = Application.GetOpenFilename(Title:=sTitle, FileFilter:=sFilter)
If sPath = False Then
MsgBox "You canceled.", vbExclamation, "Canceled"
GoTo ProcExit
End With
Application.ScreenUpdating = False
' Worksheet
Dim swb As Workbook: Set swb = Workbooks.Open(sPath)
On Error Resume Next
Dim sws As Worksheet: Set sws = swb.Worksheets(sName)
On Error GoTo 0
If sws Is Nothing Then
CloseWithoutSaving swb
MsgBox "The worksheet '" & sName & "' does not exist.", _
vbCritical, "No Worksheet"
GoTo ProcExit
End If
' Range
Dim fCell As Range: Set fCell = sws.Range(sFirst)
With fCell
Dim lCell As Range
Set lCell = .Resize(.Worksheet.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , , xlPrevious)
If lCell Is Nothing Then
CloseWithoutSaving swb
MsgBox "No data.", vbCritical, "No Data"
GoTo ProcExit
End If
Dim srg As Range: Set srg = .Resize(lCell.Row - .Row + 1)
End With
' Destination
' Assuming that the button is on the Destination Worksheet.
Dim dCell As Range: Set dCell = Range(dFirst)
' Otherwise, you should do something like this:
'Set dCell = ThisWorkbook.Worksheets("DAO").Range(dFirst)
' Copy (by Assignment)
dCell.Resize(srg.Rows.Count).Value = srg.Value
CloseWithoutSaving swb
dSuccess = True
ProcExit:
If Not Application.ScreenUpdating Then
Application.ScreenUpdating = True
End If
If dSuccess Then
MsgBox "Data transferred.", vbInformation, "Success"
End If
Exit Sub
clearError:
Debug.Print "'" & ProcName & "': Unexpected Error!" & vbLf _
& " " & "Run-time error '" & Err.Number & "':" & vbLf _
& " " & Err.Description
Resume ProcExit
End Sub
Sub CloseWithoutSaving( _
ByVal wb As Workbook)
Application.DisplayAlerts = False
wb.Close False
Application.DisplayAlerts = True
End Sub

VBA Compare 2 sheets, move old comments to new sheet

Basically i have this script which compare 2 sheets, which compares a value in a column to the new sheet, if it finds the value, it will copy the information from Old sheet "B" to new sheet "B" column.
The script is working flawlessly (Thanks to the author)
I have trying to configure it to search and compare not only 1 column, but 2, if column X AND Y are equal to X AND Y in the new sheet it will do the same task.
The reason for this is that sometimes i have the value it searches for in few different rows, so when it compares it will find it at few places. While this script works perfect only when there are unique "Find" values.
Can you help me to edit so it fits "Find" and compare Column "P" & Column "V" if those are the same in new sheet, it will copy the Values in Column "B" old sheet to "B" new sheet.
Sub movecommentsInternode()
Dim Wb As Workbook
Dim wsSource As Worksheet
Dim wsDest As Worksheet
Dim rSourcePCol As Range
Dim rSourcePCell As Range
Dim rDestPCol As Range
Dim rFound As Range
Dim sFirst As String
Dim sNotFound As String
Set Wb = ActiveWorkbook
Set wsSource = Wb.Sheets("Internode Buffer")
Set wsDest = Wb.Sheets("DataInternode")
Set rSourcePCol = wsSource.Range("P2", wsSource.Cells(wsSource.Rows.Count, "P").End(xlUp))
Set rDestPCol = wsDest.Range("P2", wsDest.Cells(wsDest.Rows.Count, "P").End(xlUp))
If rSourcePCol.row < 2 Then
MsgBox "No comment available, therefor no import is needed " ' & wsSource.Name
Exit Sub
ElseIf rDestPCol.row < 2 Then
MsgBox "Data Sheet is empty, please import the correct IO-List to be able to merge the comments " ' & wsDest.Name
Exit Sub
End If
For Each rSourcePCell In rSourcePCol.Cells
Set rFound = rDestPCol.Find(rSourcePCell.Value, rDestPCol.Cells(rDestPCol.Cells.Count), xlValues, xlWhole)
If rFound Is Nothing Then
sNotFound = sNotFound & Chr(10) & rSourcePCell.Value
Else
sFirst = rFound.Address
Do
rFound.Offset(, -14).Value = rSourcePCell.Offset(, -14).Value
Set rFound = rDestPCol.FindNext(rFound)
Loop While rFound.Address <> sFirst
End If
Next rSourcePCell
If Len(sNotFound) = 0 Then
MsgBox ("Import completed" & vbCrLf & "All comments have been merged with the new imported IO-List")
Else
MsgBox ("Import completed" & vbCrLf & "The following tag-comments have not been merged with new IO-List:" & sNotFound)
End If
End Sub
Also as a extra thing: Can you help me make it show the missing tags in a list (New sheet) insted of as comment. Will be ackward if there is hundreds of missing tags showing all in Msgbox.
Give this a try:
Sub movecommentsInternode()
Dim Wb As Workbook
Dim wsSource As Worksheet
Dim wsDest As Worksheet
Dim wsMissingTags As Worksheet
Dim rSourcePCol As Range
Dim rSourcePCell As Range
Dim rDestPCol As Range
Dim rFound As Range
Dim sFirst As String
Dim sNotFound As String
Dim bFound As Boolean
Dim aHeaders() As Variant
Dim aMissingTags As Variant
Set Wb = ActiveWorkbook
Set wsSource = Wb.Sheets("Internode Buffer")
Set wsDest = Wb.Sheets("DataInternode")
Set rSourcePCol = wsSource.Range("P2", wsSource.Cells(wsSource.Rows.Count, "P").End(xlUp))
Set rDestPCol = wsDest.Range("P2", wsDest.Cells(wsDest.Rows.Count, "P").End(xlUp))
If rSourcePCol.Row < 2 Then
MsgBox "No comment available, therefor no import is needed " ' & wsSource.Name
Exit Sub
ElseIf rDestPCol.Row < 2 Then
MsgBox "Data Sheet is empty, please import the correct IO-List to be able to merge the comments " ' & wsDest.Name
Exit Sub
End If
For Each rSourcePCell In rSourcePCol.Cells
bFound = False
Set rFound = rDestPCol.Find(rSourcePCell.Value, rDestPCol.Cells(rDestPCol.Cells.Count), xlValues, xlWhole)
If Not rFound Is Nothing Then
sFirst = rFound.Address
Do
If rSourcePCell.Offset(, 6).Value = rFound.Offset(, 6).Value Then
rFound.Offset(, -14).Value = rSourcePCell.Offset(, -14).Value
bFound = True
End If
If bFound = True Then Exit Do 'First match for both columns found, exit find loop (this line can be removed if preferred)
Set rFound = rDestPCol.FindNext(rFound)
Loop While rFound.Address <> sFirst
End If
If bFound = False Then sNotFound = sNotFound & "|" & rSourcePCell.Value & vbTab & rSourcePCell.Offset(, 6).Value
Next rSourcePCell
If Len(sNotFound) = 0 Then
MsgBox ("Import completed" & vbCrLf & "All comments have been merged with the new imported IO-List")
Else
On Error Resume Next
Set wsMissingTags = Wb.Worksheets("Missing Tags")
On Error GoTo 0
If wsMissingTags Is Nothing Then
'Missing Tags worksheet doesn't exist, create it and add headers
aHeaders = Array(wsSource.Range("P1").Value, wsSource.Range("V1").Value)
Set wsMissingTags = Wb.Worksheets.Add(After:=Wb.Worksheets(Wb.Worksheets.Count))
wsMissingTags.Name = "Missing Tags"
With wsMissingTags.Range("A1").Resize(, UBound(aHeaders) - LBound(aHeaders) + 1)
.Value = aHeaders
.Font.Bold = True
.Borders(xlEdgeBottom).LineStyle = xlContinuous
End With
Else
'Missing Tags worksheet already exists, clear previous contents (if any)
wsMissingTags.Range("A1").CurrentRegion.Offset(1).ClearContents
End If
aMissingTags = Split(Mid(sNotFound, 2), "|")
With wsMissingTags.Range("A2").Resize(UBound(aMissingTags) - LBound(aMissingTags) + 1)
.Value = Application.Transpose(aMissingTags)
.TextToColumns .Cells, xlDelimited, Tab:=True
End With
MsgBox "Import completed" & vbCrLf & "See the Missing Tags worksheet for a list of tag-comments that have not been merged with new IO-List."
End If
End Sub
It is a fine code. I modified and tried it and find working as per my understanding of your requirement The modified full code is:
Sub movecommentsInternode()
Dim Wb As Workbook
Dim wsSource As Worksheet
Dim wsDest As Worksheet
Dim rSourceHCol As Range
Dim rDestHCol As Range
Dim rdestHCell As Range
Dim rSourceHCell As Range
Dim rSourceHCol2 As Range 'added
Dim rDestHCol2 As Range 'added
Dim rSourceHCell2 As Range 'added
Dim rdestHCell2 As Range 'added
Dim rFound As Range
Dim sFirst As String
Dim sNotFound As String
Set Wb = ActiveWorkbook
Set wsSource = Wb.Sheets("Internode Buffer")
Set wsDest = Wb.Sheets("DataInternode")
Set rSourceHCol = wsSource.Range("H2", wsSource.Cells(wsSource.Rows.Count, "H").End(xlUp))
Set rDestHCol = wsDest.Range("H2", wsDest.Cells(wsDest.Rows.Count, "H").End(xlUp))
'Next two lines added
Set rSourceHCol2 = wsSource.Range("V2", wsSource.Cells(wsSource.Rows.Count, "V").End(xlUp))
Set rDestHCol2 = wsDest.Range("V2", wsDest.Cells(wsDest.Rows.Count, "V").End(xlUp))
If rSourceHCol.Row < 2 Or rSourceHCol2.Row < 2 Then ' condition modified
MsgBox "No comment available, therefor no import is needed " ' & wsSource.Name
Exit Sub
ElseIf rDestHCol.Row < 2 Or rDestHCol2.Row < 2 Then ' condition modified
MsgBox "Data Sheet is empty, please import the correct IO-List to be able to merge the comments " ' & wsDest.Name
Exit Sub
End If
For Each rSourceHCell In rSourceHCol.Cells
Set rSourceHCell2 = rSourceHCell.Offset(0, 14) 'corresponding value in V Col Source Sheet
Set rFound = rDestHCol.Find(rSourceHCell.Value, rDestHCol.Cells(rDestHCol.Cells.Count), xlValues, xlWhole)
If rFound Is Nothing Then
sNotFound = sNotFound & Chr(10) & rSourceHCell.Value
Else
sFirst = rFound.Address
Do
'Next two lines and if clause added
Set rdestHCell2 = rFound.Offset(0, 14) 'corresponding value in V Col Destination Sheet
If rSourceHCell2.Value = rdestHCell2.Value Then ' added
rFound.Offset(0, -6).Value = rSourceHCell.Offset(0, -6).Value 'offset from H to B
End If
Set rFound = rDestHCol.FindNext(rFound)
Loop While rFound.Address <> sFirst
End If
Next rSourceHCell
If Len(sNotFound) = 0 Then
MsgBox ("Import completed" & vbCrLf & "All comments have been merged with the new imported IO-List")
Else
MsgBox ("Import completed" & vbCrLf & "The following tag-comments have not been merged with new IO-List:" & sNotFound)
End If
End Sub
Edit: line Set rSourceHCell2 = rSourceHCell.Offset(0, 14) moved after line For Each rSourceHCell In rSourceHCol.Cells . If it does not work try to use If StrComp(rSourceHCell2.Value, rDestHCell2.Value) = 0 Then in place of If rSourceHCell2.Value = rdestHCell2.Value Then

Show comments for each sheet of a workbook in a MsgBox

I am trying to display all comment text for each worksheet in the Activeworkbook in a MsgBox (for each comment).
My code isn't throwing an error, so I know I am close.
Sub ShowAllWorkbookcomments()
On Error Resume Next
Dim ws As Worksheet
Dim rng As Range
Dim cell As Variant
Dim cmt As String
Dim commentcount As Integer
Set ws = ActiveWorkbook.Worksheets(1)
Set rng = ActiveSheet.Cells.SpecialCells(xlCellTypeComments)
commentcount = rng.Count
'cmt = ws.rng.Comment.Text
Dim varComment As String
Dim c As Comment
For Each ws In ActiveWorkbook.Worksheets
Select Case commentcount
Case 0
MsgBox "No Comment", vbExclamation
Resume Next
Case Is > 0
For Each cell In rng
varComment = c.Text
MsgBox varComment, vbInformation
Next cell
End Select
Set rng = Nothing
Next ws
End Sub
You were close, just needed to get the Set rng = ActiveSheet.Cells.SpecialCells(xlCellTypeComments) inside the For Each ws In ActiveWorkbook.Worksheets loop.
Also, added another way to trap the possibility of a worksheet having no comments, and removed the unnecessary Select Case.
Try the code below:
Option Explicit
Sub ShowAllWorkbookcomments()
Dim ws As Worksheet
Dim rng As Range
Dim cell As Range
Dim cmt As String
Dim varComment As String
For Each ws In ActiveWorkbook.Worksheets
On Error Resume Next
Set rng = ws.Cells.SpecialCells(xlCellTypeComments)
On Error GoTo 0
If Not rng Is Nothing Then '<-- current worksheet has comments
For Each cell In rng.Cells
'varComment = cell.Comment.text
varComment = "worksheet " & ws.Name & " comment " & cell.Comment.text ' <-- added the worksheet name as reference
MsgBox varComment, vbInformation
Next cell
Else '<-- current worksheet has No comments >> rng is Nothing
'MsgBox "No Comment", vbExclamation
MsgBox "worksheet " & ws.Name & " has No Comments", vbExclamation ' <-- added the worksheet name as reference
End If
Set rng = Nothing
Next ws
End Sub
As mentioned in one of the comments above, the above logic will cause the MsgBox to be shown for each of the cells in a merged range. The following logic will loop-through the comments in a given sheet, it will work for merged rows/cols scenario as well.
For Each CommentedSheets In ActiveWorkbook.Worksheets
If CommentedSheets.Comments.Count = 0 Then
MsgBox "worksheet " & CommentedSheets.Name & " has No Comments", vbExclamation
Else
For Each Individual_Comment In CommentedSheets.Comments
varComment = "worksheet " & CommentedSheets.Name & " comment " & Individual_Comment.text
MsgBox varComment, vbInformation

Resources