How can I clear only one worksheet? - excel

I am trying to clear the contents of worksheet one after the following macro. I have tried using Sheets("Sheet1").UsedRange.ClearContents, but it seems to clear both sheets. I have a feeling it has to do with the Do...Until loop I have, despite putting the clear line right after Loop. This is the first macro I have written and am still learning hence all the comments.
Sub LookUpTable()
'Declare Variables'
Dim rngB As Range
Dim Rng As Range
Dim sh As Worksheet
Dim iCountComma
Dim VarArr As Variant
Dim i As Long
'Separate Cell C2 into Column C by Comma'
Set sh = Sheets("Sheet1")
Set rngB = sh.Range("C2")
For Each Rng In rngB
If InStr(Rng, ",") > 0 Then
iCountComma = Len(Rng) - Len(Replace(Rng, ",", ""))
VarArr = Split(Rng, ",")
For i = 0 To iCountComma
Rng.Offset(i) = Trim(VarArr(i))
Next
End If
Next
'I Don't really know what these do'
Application.CutCopyMode = True
Application.ScreenUpdating = True
'Declare Variables'
Dim BedPre As String
Dim BedSuf As String
Dim HISPre As String
Dim HISSuf As String
Dim ID As String
Dim Bed As String
Dim HIS As String
Dim NextRow As Long
'Assign cell values to variables'
BedPre = Range("A2").Value
BedSuf = Range("B2").Value
HISPre = Range("D2").Value
HISSuf = Range("E2").Value
ID = Range("F2").Value
'Select Cell C2'
Sheets("Sheet1").Select
Range("C2").Select
'Loop until empty value in Column C'
Do Until ActiveCell.Value = ""
'Find last empty cell in sheet 2'
NextRow = Sheets("Sheet2").Cells(Sheets("Sheet2").Rows.Count, "A").End(xlUp).Offset(1, 0).Row
'Concantenate cells and append Sheet 2'
Bed = BedPre & ActiveCell & BedSuf
HIS = HISPre & ActiveCell & HISSuf
Sheets("Sheet2").Cells(NextRow, 1) = Bed
Sheets("Sheet2").Cells(NextRow, 2) = HIS
Sheets("Sheet2").Cells(NextRow, 3) = ID
ActiveCell.Offset(1, 0).Select
Loop
Sheets("Sheet1").UsedRange.ClearContents
End Sub

I dont see data clear both sheets.
you can use this code
Sub LookUpTable()
'Declare Variables'
Dim Rng As Range
Dim VarArr As Variant
Dim i As Long
Dim BedPre As String
Dim BedSuf As String
Dim HISPre As String
Dim HISSuf As String
Dim ID As String
Dim Bed As String
Dim HIS As String
Dim NextRow As Long
'Assign cell values to variables'
With Sheets("Sheet1")
BedPre = Range("A2").Value
BedSuf = Range("B2").Value
HISPre = Range("D2").Value
HISSuf = Range("E2").Value
ID = Range("F2").Value
Set Rng = .Range("C2")
End With
NextRow = Sheets("Sheet2").Cells(Sheets("Sheet2").Rows.Count, "A").End(xlUp).Offset(1, 0).Row
If InStr(Rng, ",") > 0 Then
VarArr = Split(Rng, ",")
For i = 0 To UBound(VarArr)
Bed = BedPre & Trim(VarArr(i)) & BedSuf
HIS = HISPre & Trim(VarArr(i)) & HISSuf
NextRow = NextRow + 1
Sheets("Sheet2").Cells(NextRow, 1) = Bed
Sheets("Sheet2").Cells(NextRow, 2) = HIS
Sheets("Sheet2").Cells(NextRow, 3) = ID
Next
End If
Sheets("Sheet1").Range("A2:F2").ClearContents
End Sub

Related

How do I allow duplicates in VBA?

I'm trying to compare column A in sheet2 to column A in sheet1 and when there's a match, copy the row from sheet1 to sheet3 with the same order. And if there is a repetition, it should be included too. I also need it to show the mismatching values empty. I did this macro but I can not allow the duplicates to be included.
Sub compareAndCopy()
Dim lastRowE As Long
Dim lastRowF As Long
Dim lastRowM As Long
Dim foundTrue As Boolean
' stop screen from updating to speed things up
Application.ScreenUpdating = False
lastRowE = Sheets("Sheet2").Cells(Sheets("Sheet2").Rows.Count, "A").End(xlUp).Row
lastRowF = Sheets("Sheet1").Cells(Sheets("Sheet1").Rows.Count, "A").End(xlUp).Row
lastRowM = Sheets("Sheet3").Cells(Sheets("Sheet3").Rows.Count, "B").End(xlUp).Row
For i = 1 To lastRowE
foundTrue = False
For j = 1 To lastRowF
If Sheets("Sheet2").Cells(i, 1).Value = Sheets("Sheet1").Cells(j, 1).Value Then
lastRowM = lastRowM + 1
Sheets("Sheet1").Rows(i).Copy Destination:= _
Sheets("Sheet3").Rows(lastRowM)
foundTrue = True
Exit For
End If
Next j
'If Not foundTrue Then
' MsgBox ("didn't find string: " & Sheets("Sheet2").Cells(i, 2).value)
'End If
Next i
' allow screen updating
Application.ScreenUpdating = True
End Sub
Group Data
Loops through probably unique values in column A of Sheet2.
For each cell value, it uses the Find and FindNext methods to find all the matching cells in column A of Sheet1.
Then it writes each of the cell values to a key, and using Union, combines each matching cell to a range object in the corresponding item.
Then it loops through the dictionary and copies the entire rows of each item (range) to Sheet3.
Finally, it clears the newly added values in column A of Sheet3.
The result in Sheet3 is data from Sheet1 grouped by the values in column A of Sheet2.
Option Explicit
Sub CompareAndCopy()
Const eName As String = "Sheet2"
Const eCol As String = "A"
Const efRow As Long = 1 ' don't you have headers?
Const fName As String = "Sheet1"
Const fCol As String = "A"
Const ffRow As Long = 1 ' don't you have headers?
Const mName As String = "Sheet3"
Const mCol As String = "B" ' "A" is empty!
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ews As Worksheet: Set ews = wb.Worksheets(eName)
Dim elRow As Long: elRow = ews.Cells(ews.Rows.Count, eCol).End(xlUp).Row
If elRow < efRow Then Exit Sub ' no data
Dim erg As Range: Set erg = ews.Cells(efRow, eCol).Resize(elRow - efRow + 1)
'Debug.Print erg.Address
Dim fws As Worksheet: Set fws = wb.Worksheets(fName)
Dim flRow As Long: flRow = fws.Cells(fws.Rows.Count, fCol).End(xlUp).Row
If flRow < ffRow Then Exit Sub ' no data
Dim frg As Range:
Set frg = fws.Cells(ffRow, fCol).Resize(flRow - ffRow + 1)
'Debug.Print frg.Address
Dim mws As Worksheet: Set mws = wb.Worksheets(mName)
Dim mifCell As Range
Set mifCell = mws.Cells(mws.Rows.Count, mCol).End(xlUp).Offset(1) _
.EntireRow.Columns("A") ' entire rows
Dim mfCell As Range: Set mfCell = mifCell
'Debug.Print mfCell.Address
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare
Application.ScreenUpdating = False
Dim frCount As Long: frCount = frg.Rows.Count
Dim eCell As Range
Dim eValue As Variant
Dim fCell As Range
Dim FirstAddress As String
For Each eCell In erg.Cells
eValue = eCell.Value
Set fCell = frg.Find(eValue, frg.Cells(frCount), xlFormulas, xlWhole)
If Not fCell Is Nothing Then
FirstAddress = fCell.Address
Do
If dict.Exists(eValue) Then
Set dict(eValue) = Union(dict(eValue), fCell)
Else
Set dict(eValue) = fCell
End If
Set fCell = frg.FindNext(fCell)
Loop Until fCell.Address = FirstAddress
End If
Next eCell
If dict.Count = 0 Then Exit Sub ' no data¸
Dim rg As Range
Dim Item As Variant
Dim irCount As Long
For Each Item In dict.Items
irCount = Item.Cells.Count
'Debug.Print Item.Address, irCount
Item.EntireRow.Copy mfCell.EntireRow
Set mfCell = mfCell.Offset(irCount)
Next Item
mifCell.Resize(mfCell.Row - mifCell.Row).ClearContents ' or .Clear
Application.ScreenUpdating = True
MsgBox "Data grouped.", vbInformation
End Sub

Naming each column of a variable range based on data in one column

I am trying to name each column header with the same base title, but changing the value of a unit, all the data for this unit is in column D. My vba skills are very basic. When I run the code, the titles appear but the actual values do not and there is a space of one column between every title. I'm not sure why this is happening
Private Sub Viscosity_Temperature()
Dim dsvt As Worksheet
Dim dst As Worksheet
Dim sr As Range
Dim t As Range
Dim rng As Range
Dim rn As Integer
Dim rn2 As Integer
Dim cl As String
Dim i As Integer
Set dst = Worksheets("Template 2 - Down Sweep")
Sheets.Add.Name = "DownSweep ViscosityTemperature"
Set dsvt = Worksheets("DownSweep ViscosityTemperature")
dst.Range(dst.Range("H1"), dst.Range("H1").End(xlDown)).Copy
dsvt.Range("D1").PasteSpecial Paste:=xlPasteValues
dst.Range(dst.Range("D1"), dst.Range("D1").End(xlDown)).Copy
dsvt.Range("A1").PasteSpecial Paste:=xlPasteValues
dst.Range(dst.Range("C1"), dst.Range("C1").End(xlDown)).Copy
dsvt.Range("B1").PasteSpecial Paste:=xlPasteValues
dst.Range(dst.Range("F1"), dst.Range("F1").End(xlDown)).Copy
dsvt.Range("C1").PasteSpecial Paste:=xlPasteValues
Set rng = dsvt.Range(dsvt.Range("D1"), dsvt.Range("D1").End(xlDown))
rn = rng.Rows.Count
rn2 = rn + 6
cl = Split(Cells(1, rn2).Address, "$")(1)
Set sr = dsvt.Range(dsvt.Range("D2"), dsvt.Range("D2").End(xlDown))
Set t = dsvt.Range("F1:" & cl & "1")
i = 1
For i = 1 To rn
t(1, i).Value = "Viscosity at" & sr(i, 4) & "1/s"
i = i + 1
Next i
End Sub
Any help would be appreciated.
I found the error - searching for values in a single column and adding 1 to I when it is nexted.
Private Sub Viscosity_Temperature()
Dim dsvt As Worksheet
Dim dst As Worksheet
Dim sr As Range
Dim t As Range
Dim rng As Range
Dim rn As Integer
Dim rn2 As Integer
Dim cl As String
Dim i As Integer
Set dst = Worksheets("Template 2 - Down Sweep")
Sheets.Add.Name = "DownSweep ViscosityTemperature"
Set dsvt = Worksheets("DownSweep ViscosityTemperature")
dst.Range(dst.Range("H1"), dst.Range("H1").End(xlDown)).Copy
dsvt.Range("D1").PasteSpecial Paste:=xlPasteValues
dst.Range(dst.Range("D1"), dst.Range("D1").End(xlDown)).Copy
dsvt.Range("A1").PasteSpecial Paste:=xlPasteValues
dst.Range(dst.Range("C1"), dst.Range("C1").End(xlDown)).Copy
dsvt.Range("B1").PasteSpecial Paste:=xlPasteValues
dst.Range(dst.Range("F1"), dst.Range("F1").End(xlDown)).Copy
dsvt.Range("C1").PasteSpecial Paste:=xlPasteValues
Set rng = dsvt.Range(dsvt.Range("D1"), dsvt.Range("D1").End(xlDown))
rn = rng.Rows.Count
rn2 = rn + 6
cl = Split(Cells(1, rn2).Address, "$")(1)
Set sr = dsvt.Range(dsvt.Range("D2"), dsvt.Range("D2").End(xlDown))
Set t = dsvt.Range("F1:" & cl & "1")
i = 1
For i = 1 To rn - 1
t(1, i).Value = "Viscosity at " & sr(i, 1) & " 1/s"
Next i
End Sub
1. List item

Storing a Dynamic Range in Range variable

I am trying to get unique values from dynamic F column and store it in an array. I am getting "Object Required error for my code while setting Selection variable to a dynamic range. Please help.
Sub UniqueFilter()
Dim tmp As String
Dim arr() As String
Dim Selection As Range
Dim lrow As Long
Dim str As String
Dim cell As Range
Dim sht As Worksheet
Set sht = ThisWorkbook.Worksheets("14Feb19")
sht.Activate
'Set Selection = sht.Range(sht.Cells(1, 6), sht.Cells(Rows.Count, 6).End (xlUp)).Select
lrow = shData.Range("F" & Rows.Count).End(xlUp).Row
Set Selection = sht.Range("F2:F" & lrow).Select
If Not Selection Is Nothing Then
For Each cell In Selection
If (cell <> "") And (InStr(tmp, cell) = 0) Then
tmp = tmp & cell & "|"
End If
Next cell
End If
If Len(tmp) > 0 Then tmp = Left(tmp, Len(tmp) - 1)
arr = Split(tmp, "|")
End Sub
You can achieve your goal without having to use Selection at all.
Just copy the range content and transpose it into an array:
Sub UniqueFilter()
Dim arr() As String
Dim tmp As Variant
Dim lrow As Long
Dim sht As Worksheet
Dim index As Integer
Dim count As Integer
Set sht = ThisWorkbook.Worksheets("14Feb19")
sht.Activate
lrow = sht.Range("F" & Rows.count).End(xlUp).Row
'Copying and trasposing selected Range
tmp = Application.Transpose(sht.Range("F2:F" & lrow).Value)
'Cleaning from temp array all empty values
count = 1
For index = 1 To UBound(tmp, 1) - LBound(tmp, 1) + 1
ReDim Preserve arr(1 To count)
If tmp(index) <> "" Then
arr(count) = tmp(index)
count = count + 1
End If
Next
End Sub
(special thanks to #Nathan_Sav, who helped simplifying the code)

Moving columns containg "Total" at the end of the pivot(after paste special) if the cells of second row contain the word "Total"

' If the cells of second row contain the word "Total" ,I want to copy paste the entire column of that cell to the end of the table.The following code gives no output. Can someone please help me identify my mistake?
enter image description here
Dim PRTSLastRow As Long
Dim PRTSLastCol As Long
Dim ColLtr As String
Dim LastColLtr As String
Dim Total As String
Dim j as Integer
W = ActiveWorkbook.Name
PRTSLastCol = Worksheets("PRTSCarrierCount").Cells(1, Columns.Count).End(xlToLeft).Column
PRTSLastRow = Worksheets("PRTSCarrierCount").Cells(Rows.Count, 1).End(xlUp).Row
j = 1
Workbooks(W).Sheets("PRTSCarrierCount").Activate
For i = 1 To PRTSLastCol
Total = Cells(1, i).Value
If InStr(1, CStr(Total), "Total") > 0 Then
ColLtr = Replace(Cells(1, i).Address(True, False), "$1", "")
LastColLtr = Replace(Cells(1, PRTSLastCol + j).Address(True, False), "$1", "")
Range("ColLtr & 1: & ColLtr & PRTSLastRow").Select
'Columns("ColLtr & : & ColLtr").Select
Selection.Copy
Range("LastColLtr & 1").Select
ActiveSheet.Paste
j = j + 1
End If
Next i
Something like this?
Option Explicit
Sub Thing()
Dim PRTSLastRow As Long
Dim PRTSLastCol As Long
Dim ColLtr As String
Dim LastColLtr As String
Dim Total As String
Dim W As Workbook
Dim i As Long
Dim ws As Worksheet
Set W = ThisWorkbook 'Or ActiveWorkbook
Set ws = W.Worksheets("PRTSCarrierCount")
PRTSLastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row
PRTSLastCol = GetLastCol(ws, 1)
With ws
For i = 1 To PRTSLastCol
Total = LCase$(.Cells(1, i).Text)
If InStr(1, Total, "total") > 0 Then
ColLtr = Replace(.Cells(1, i).Address(True, False), "$1", "")
.Range(ColLtr & "1:" & ColLtr & PRTSLastRow).Copy .Cells(1, GetLastCol(ws, 1) + 1)
i = i + 1
End If
Next i
End With
End Sub
Public Function GetLastCol(ByVal ws As Worksheet, rowNum As Long) As Long
With ws
GetLastCol = .Cells(rowNum, Columns.Count).End(xlToLeft).Column
End With
End Function
Or with Find
Public Sub Thing2()
Dim PRTSLastRow As Long
Dim PRTSLastCol As Long
Dim ColLtr As String
Dim LastColLtr As String
Dim Total As String
Dim W As Workbook
Dim ws As Worksheet
Dim searchRng As Range
Set W = ThisWorkbook 'Or ActiveWorkbook
Set ws = W.Worksheets("PRTSCarrierCount")
PRTSLastCol = GetLastCol(ws, 1)
Total = "total"
With ws
PRTSLastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
Set searchRng = .Range(.Cells(1, 1), .Cells(1, PRTSLastCol))
Dim gatheredRange As Range
Set gatheredRange = GatherRanges(Total, searchRng, PRTSLastRow)
If Not gatheredRange Is Nothing Then
gatheredRange.Copy .Cells(1, GetLastCol(ws, 1) + 1)
End If
End With
End Sub
Public Function GatherRanges(ByVal Total As String, ByVal searchRng As Range, ByVal PRTSLastRow As Long) As Range
Dim foundCell As Range
Set foundCell = searchRng.Find(Total)
If foundCell Is Nothing Then
MsgBox "Search term not found"
End
End If
Dim firstfoundCellAddress As String
firstfoundCellAddress = foundCell.Address
Dim gatheredRange As Range
Set gatheredRange = foundCell.Resize(PRTSLastRow, 1)
Do
Set foundCell = searchRng.FindNext(foundCell)
Set gatheredRange = Union(gatheredRange, foundCell.Resize(PRTSLastRow, 1))
Loop While firstfoundCellAddress <> foundCell.Address
Set GatherRanges = gatheredRange
End Function
Reference:
https://excelmacromastery.com/excel-vba-find/

Concatenate unique cell values in every row

How can I concatenate unique cell values in every row to adapt in the code below. Removing duplicate values in a cell. Result after macro is the second image.
Sub Concatenar()
Dim myRange As Range
Dim c As Long
Dim r As Long
Dim txt As String
Set myRange = Application.InputBox("Selecione a primeira e a última célula:", Type:=8)
For r = 1 To myRange.Rows.Count
For c = 1 To myRange.Columns.Count
If myRange(r, c).Text <> "" Then
txt = txt & myRange(r, c).Text & vbLf
End If
Next
If Right(txt, 1) = vbLf Then
txt = Left(txt, Len(txt) - 1)
End If
myRange(r, 1) = txt
txt = ""
Next
Range(myRange(1, 2), myRange(1, myRange.Columns.Count)).EntireColumn.Delete
End Sub
This does what you want, I believe. It pastes/tranposes the values to a temporary workbook, uses RemoveDuplicates to trim them down, and Join to munge them all together. It then pastes the munged values back into column A of the original workbook and deletes the other columns.
Because of the destructive nature of this code, you must test it on a copy of your data:
Sub CrazyPaste()
Dim wsSource As Excel.Worksheet
Dim rngToConcat As Excel.Range
Dim wbTemp As Excel.Workbook
Dim wsPasted As Excel.Worksheet
Dim rngPasted As Excel.Range
Dim i As Long
Dim LastRow As Long
Dim Results() As String
Set wsSource = ActiveSheet
Set rngToConcat = wsSource.UsedRange
Set wbTemp = Workbooks.Add
Set wsPasted = wbTemp.Worksheets(1)
wsSource.UsedRange.Copy
wsPasted.Range("A1").PasteSpecial Transpose:=True
Set rngPasted = wsPasted.UsedRange
ReDim Results(1 To rngPasted.Columns.Count)
For i = 1 To rngPasted.Columns.Count
If WorksheetFunction.CountA(rngPasted.Columns(i)) = 0 Then
Results(i) = ""
Else
rngPasted.Columns(i).RemoveDuplicates Columns:=1, Header:=xlNo
LastRow = Cells(wsPasted.Rows.Count, i).End(xlUp).Row
Results(i) = Replace(Join(Application.Transpose(rngPasted.Columns(i).Resize(LastRow, 1)), vbCrLf), _
vbCrLf & vbCrLf, vbCrLf)
End If
Next i
With wsSource
.Range("A1").Resize(i - 1, 1) = Application.Transpose(Results)
.Range(.Cells(1, 2), .Cells(1, .Columns.Count)).EntireColumn.Delete
wbTemp.Close False
End With
End Sub
In my limited testing, the only situation where this might yield unwanted results is when a cell in the first column is blank, but there's other data in that row. The resulting cell would then start with a blank.

Resources