Excel VBA - How to select the whole table of borders - vba

i am very new to Excel VB. I am hoping you can assist with my problem.
I have several tables like this
The tables can be edited such as by inserting new rows, etc by the user.
I want to highlight and copy the latest table (the one at the very last row) and paste it at the next available space, 3 rows down.
I managed to do this, but I can only highlight and copy the cells with data. So should there be an empty row in the middle of the table, or an empty last row with borders, it would not copy correctly, as shown here:
I do still need to copy everything within the borders including empty rows, but I lack the skills and knowledge to do so. I hope you can assist.
The following is my code:
Sub CopyPaste()
LastRow = Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
FirstColumn = Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlNext).Column
LastColumn = Cells.Find("*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
BelowLastName = Cells.Find("", After:=Cells(LastRow, FirstColumn), SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Row
Cells(BelowLastName, FirstColumn).Select 'This selects C5 (refer image)
Selection.Offset(-1).Select 'This selects C4 (refer image)
Range(Selection, Cells(LastRow, LastColumn)).Select 'This highlights whole table
Selection.Copy
Cells(LastRow, FirstColumn).Select
ActiveCell.Offset(3).Select
ActiveSheet.Paste
Application.CutCopyMode = False
End Sub

Try this
Sub x()
Dim rEnd As Range, rStart As Range, i As Long
Set rEnd = Range("C" & Rows.Count).End(xlUp)
Do While rEnd.Offset(i).Borders(xlEdgeBottom).LineStyle = xlContinuous
i = i - 1
Loop
Set rStart = rEnd.Offset(i + 1)
Range(rStart, rEnd).Resize(, 8).Copy rEnd.Offset(3)
End Sub

Related

Auto Populate Formula to end of series in excel

I am having an issue with a piece of VBA in excel and am looking for assistance.
I require a piece of code to auto populate a formula in excel through a series of data, the series will vary in length and will occupy columns C:I.
I have been using this piece of code without issue for quiet a while:
Sub Auto_Fill_Formula()
Sheets("Sheet1").Select
Dim LstRow As Long
With Sheets("Sheet1")
LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
.Range("A2:A" & LastRow).Formula = "Formula added here"
Application.CutCopyMode = False
End With
End Sub
However as the formula is being added to the leftmost column it only populates the first cell, cell A2.
How can I modify this code to work when the leftmost column is empty?
Thank you,
Wayne
You can use Find to find the last used row in C:I by searching backwards from row 1. You should also use Option Explicit to pick up typos in variable names (LstRow).
Sub Auto_Fill_Formula()
Sheets("Sheet1").Select
Dim LastRow As Long, r As Range
With Sheets("Sheet1")
Set r = .Range("C:I").Find(What:="*", After:=.Range("C1"), Lookat:=xlWhole, SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, MatchCase:=False, SearchFormat:=False)
If Not r Is Nothing Then
LastRow = r.Row
.Range("A2:A" & LastRow).Formula = "Formula added here"
End If
End With
End Sub

VBA find select all then shift all adjacent cells to the right

I'm trying to write a macro that will sort a work book that is generated by a system at work. I have attempted to chopshop some code together from other posts on this site with no success.
The goal is to search column A for any cells that contain either "IN" or "OUT" then move every thing to the right of these cells one cell to the right.
I have some code that works for the first output but it will only ever ready the first out put I know why it doesn't work but I don't know how to fix it.
Any help would be much appreciated,
Thanks,
Sub Data_only()
'
' Reworks_Data_only Macro
'
' Keyboard Shortcut: Ctrl+k
'
Columns("J:AB").Select
Selection.ClearContents
Cells.Select
Cells.EntireColumn.AutoFit`enter code here`
' ^ Cuts out unused columns and autofits the rest
Columns("A:A").Select
Selection.Find(What:="in", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
' ^Searches Column A for "IN"
ActiveCell.Offset(, 1).Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
' ^Selects the found cell and shift the whole row to the right
End Sub
EDIT
This is a mock up of the file im looking to change, there would normally be a few hundred batches and a lot more columns but it should be workable.
batches mock up
Something like that would be possible if you like to use the Find function ...
Option Explicit
Public Sub Data_only()
MoveByFind "IN"
MoveByFind "OUT"
End Sub
Public Function MoveByFind(FindString As String)
Dim Found As Range
Set Found = Columns("A:A").Find(What:=FindString, LookIn:=xlFormulas, LookAt:=xlWhole, _
SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
If Not Found Is Nothing Then
Dim firstAddress As String
firstAddress = Found.Address 'remember first find for no endless loop
Do
Found.Offset(0, 1).Insert Shift:=xlToRight 'move cells right
Set Found = Columns("A:A").FindNext(After:=Found) 'find next
Loop While Not Found Is Nothing And Found.Address <> firstAddress 'loop until end or nothing found
End If
End Function
You can do this with a simple loop, rather than using the Find function:
Dim i as Long, LR as Long
LR = Cells(Rows.Count,1).End(xlUp).Row
For i = 2 to LR 'Assumes you have a header in row 1
If Cells(i,1).Value = "IN" OR Cells(i,1).Value = "OUT" Then
Cells(i,2).Insert Shift:=xlToRight
End If
Next i
Note that In and Out are case-sensitive.
You could also do this with the Find function, though you would find all, or use find next, and use the .insert as you've doen in your code.
Edit:
Assuming that the issue is hidden characters, InStr can be used:
Dim i As Long, LR As Long, j As Integer, k As Integer
LR = Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To LR 'Assumes you have a header in row 1
j = InStr(Cells(i, 1).Value, "IN")
k = InStr(Cells(i, 1).Value, "OUT")
If j > 0 Or k > 0 Then
Cells(i, 2).Insert Shift:=xlToRight
End If
Next i

Autofiltering from a different sheet

I am trying to create a VBA macro for post processing data, and it currently has a "Raw Data" sheet for the first sheet, and my post processing tools on the second sheet. What I have so far is a button that will search the data and create plots for the desired variables, but it pulls data for all of the test points. What I want to do is to be able to filter by test point from the data review sheet. What would be ideal would be to have an autofilter type dropdown menu on my post processing sheet where the test point can be selected, and the data on the previous sheet would be filtered.
Here's the search function I've been using:
Dim TestPt As Long
Dim rows As Long
rows = Sheets(1).UsedRange.rows.Count
'
Sheets(1).Select
Cells.Find(What:="TargetTestPointNumber", After:=ActiveCell, LookIn:=xlFormulas, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
, SearchFormat:=False).Activate
TestPt = ActiveCell.Column
Any help would be appreciated!
I'm not 100% sure what you needed exactly. But this code does a comparison between the value you want and the data sheet. If its = it will copy it to Row D so if you have stuff there you will need to change it. Also it assumes the data is in row 1.
Dim i As Long, lastRowD As Long, lastRowA As Long
With Sheets("datasheetname")
lastRowA = .Range("A" & .Rows.count).End(xlUp).Row
For i = 1 To lastRowA
lastRowD = .Range("D" & .Rows.count).End(xlUp).Row
If .Cells(i, 1).Value = "testvalue" Then
.Cells(lastRowD, 4).Value = "testvalue"
End If
Next i
.Range("D1", "D" & lastRowD).Select
ActiveSheet.Shapes.AddChart.Select
ActiveChart.ChartType = xlXYScatter
ActiveChart.SetSourceData Source:=Range("'datasheetname'!$D$1:$D" & lastRowD)
End With
note youll need to change test value and datasheetnames. As well as any of the column info. I tried it and it works. I just have no idea if this is what you need. If you need to copy more than 1 row, you would change in the if how many to do.
.cells(lastRowD,5).value= .cells(i,2).value etc
Sorry for the messy code, but I found this to work for me. Basically I copied the unique test point value to the other sheet, linked them to a ComboBox, and linked a macro to run with the ComboBox to autofilter the data on the other sheet. I'm sure there has to be a better way, but it works for me.
Sub ValueSelectionData()
'
Dim TestPt As Long
Dim rows As Long
Dim Value As Long 'used to select test point
rows = Sheets(1).UsedRange.rows.Count 'Row count on data sheet
Value = Sheets(2).Cells(2, 6).Value 'value linked to ComboBox selection
'
Sheets(2).Columns("A:A").ClearContents
Sheets(1).Select
Cells.Find(What:="TargetTestPointNumber", After:=ActiveCell, LookIn:=xlFormulas, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
, SearchFormat:=False).Activate 'searches for test point column in data
TestPt = ActiveCell.Column
Range(Sheets(1).Cells(2, TestPt), Sheets(1).Cells(rows, TestPt)).AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Range(Sheets(2).Cells(1, 1), Sheets(2).Cells(1, 1)), Unique:=True
If Value > 0 Then
Sheets(1).Select
Cells.Find(What:="TargetTestPointNumber", After:=ActiveCell, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False).Activate
TestPt = ActiveCell.Column
Value = Sheets(2).Cells(2, 6).Value 'desired test point to filter for
Sheets(1).Range(Sheets(1).Cells(1, TestPt), Sheets(1).Cells(rows, TestPt)).AutoFilter Field:=1, Criteria1:=Value 'autofilters data for desired test point
Else
'Clear all auto filters
If Sheets(1).AutoFilterMode Then
Sheets(1).ShowAllData
End If
End If
End Sub

VBA for searching string in a column and copy entire rows depending on the presence of certain string at adjacent cell

I am completely new for VBA.
I have excel data sheet containing numbers and strings. I want to search for certain string say 'CYP' in column I then look for a cell of its row at column C and copy entire rows containing the string of cell C. I want to paste in sheet 2 of the same workbook and loop it again to look for remaining CYPs in column.
Would you help me on this please?
After the suggestion from pnuts, here is my macro code
Sub Macro1()
'
' Macro1 Macro
'
'
Columns("I:I").Select
Range("I729").Activate
Selection.Find(What:="cyp", After:=ActiveCell, LookIn:=xlValues, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
ActiveWindow.SmallScroll Down:=5
Range("C749").Select
Selection.Copy
Columns("C:C").Select
Range("C734").Activate
Selection.Find(What:="EPT001TT0601C000151", After:=ActiveCell, LookIn:= _
xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext _
, MatchCase:=False, SearchFormat:=False).Activate
Rows("746:750").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Sheet2").Select
ActiveSheet.Paste
End Sub
In this code the CYP was found in I749, cell C749 was copied as string and first row in column C containing the same string was searched followed by copying of the entire row and 4 more followed by it then pasting in sheet2 of the same workbook.
What I wanted was to loop this action again and again upto the end of column I and repeat the same action.
Thank you!
I managed to solve the problem with the help of Trebor76 at Excelforum. Here I am giving solution in that way it might be helpful for some newbies like myself with similar problem.
Option Explicit
Sub Macro1()
'Written and assisted by Trebor76
'Copy an entire row from Sheet1 to Sheet2 for each unique matching item in Col. C if the text in Col. I contains the text 'CYP' (case sensitive)
'http://www.excelforum.com/excel-programming-vba-macros/962511-vba-for-searching-string-in-a-column-and-copy-rows-depending-on-string-in-adjacent-cell.html
Dim rngCell As Range
Dim objMyUniqueArray As Object
Dim lngMyArrayCounter As Long
Dim lngMyRow As Long
Dim varMyItem As Variant
Application.ScreenUpdating = False
Set objMyUniqueArray = CreateObject("Scripting.Dictionary")
For Each rngCell In Sheets("Sheet1").Range("I1:I" & Sheets("Sheet1").Range("I" & Rows.Count).End(xlUp).Row)
If InStr(rngCell, "CYP") > 0 Then
If Not objMyUniqueArray.Exists(Trim(Cells(rngCell.Row, "C"))) Then
lngMyArrayCounter = lngMyArrayCounter + 1
objMyUniqueArray.Add (Trim(Cells(rngCell.Row, "C"))), lngMyArrayCounter
varMyItem = Sheets("Sheet1").Cells(rngCell.Row, "C")
For lngMyRow = 1 To Sheets("Sheet1").Cells(Rows.Count, "C").End(xlUp).Row
If Sheets("Sheet1").Cells(lngMyRow, "C") = varMyItem Then
Rows(lngMyRow).Copy Destination:=Sheets("Sheet2").Range("A" & Sheets("Sheet2").Range("A" & Rows.Count).End(xlUp).Row + 1)
End If
Next lngMyRow
End If
End If
Next rngCell
Set objMyUniqueArray = Nothing
Application.ScreenUpdating = True
MsgBox "All applicable rows have been copied.", vbInformation
End Sub
Cheers!

Selecting columns that have values in Excel Macro (range object in VBA)

How do I modify this line in VBA to only select the columns that have values?
Set rng = Range("A1", Range("A65536").End(xlUp)).SpecialCells(xlCellTypeVisible)
I don't think I'm doing something right since the CountLarge property is several billion cells
Here is a sample of my data
#SiddharthRout Yes I only need the rows that have data. I think I have it working now with End(xlToLeft) from #JMax ... Now that I'm iterating over the cells, I can just quit the For each loop once the last row is reached. I might have this working now. – makerofthings7 14 mins ago
For this neither you need .SpecialCells nor do you need to loop through the rows :)
Here is a sample code. This will copy all the rows which have data to Sheet2 (TRIED AND TESTED)
Sub Sample()
Dim ws As Worksheet
Dim rng As Range
Dim LastRow As Long, LastCol As Long
Set ws = Sheets("Sheet1")
With ws
LastRow = .Cells.Find(What:="*", After:=.Range("A1"), Lookat:=xlPart, _
LookIn:=xlFormulas, SearchOrder:=xlByRows, SearchDirection:=xlPrevious, MatchCase:=False).Row
LastCol = .Cells.Find(What:="*", After:=.Range("A1"), Lookat:=xlPart, _
LookIn:=xlFormulas, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious, _
MatchCase:=False).Column
With .Range("A1:" & Split(Cells(, LastCol).Address, "$")(1) & LastRow)
.AutoFilter Field:=1, Criteria1:="<>"
Set rng = ws.AutoFilter.Range
rng.Offset(1, 0).Resize(rng.Rows.Count - 1).Copy _
Destination:=Sheets("Sheet2").Range("A1")
End With
End With
End Sub
SNAPSHOT
I am assuming that all cells in a particular row will have data and there won't be a case like this
#makerofthings7: I think I know what exactly you are trying to do :) you don't need to use loops to achieve what you want. Just a quick question. Is it possible that say Cell C10 might have a value but B10 might not? – Siddharth Rout 12 mins ago
If there is then we will have to set the autofilter criteria accordingly.
Edit:
WAY 2
The other way would be to sort your data, pushing the blanks way down and then copying the resulting range :)
HTH