How to select column and display its current format using VBA Macro? - vba

Please find my requirement below for which I am unable to find any solution:
1. Iterate over workSheet from workbook
2. Find all the columns containing date values using current format/type of column (Here is a trick. Worksheet is not static, it can contain any number of columns containing date values. Columns containing date values may have any name. And such worksheets can be more than one in number)
3. Apply macro on date columns for date formatting (below macro) if "Flag" value is "y"
<code>
Sub FormatDate()
If wksSecDist.Range("Flag").value = "y" Then
LastRowColA = Range("X" & Rows.Count).End(xlUp).Row
' Here I am finding total number of rows in column X
wksSecDist.Range("X2", "X" & LastRowColA).NumberFormat = "dd/mmm/yyyy"
' Here applying specified date format to Range("X2", "X10") [if last row index for column X is 10]
End If
End Sub
</code>
I am just a beginner to VBA.
Thanks in advance.

I suspect you didn't find a solution on the internet because you looked simply for a solution and not the parts needed to build your own solution.
You mention you are a VBA beginner, please take the below answer to be of educational use and begin you in getting you where you need your tool to be. Note, if it doesn't answer your question because of information that was not included, it has still answered your question and the missing information should form part of a new question. That said, lets get this function up and running.
From what you have written I have interpreted the requirement to be: -
Look over all worksheets in a workbook ('worksheets can be more than one in number')
Check every column to see if it holds a date value
If it does, set the whole column to a specific format
What is needed to accomplish this is iteration(loops), one to loop through all worksheet, and another to loop through all columns: -
The is pseudo code of the target: -
.For each Worksheet in the Workbook
..For each Column in the Worksheet
...If the Column contains dates then format it as required
..Process next column
.Process next Worksheet
We achieve this using a variable to reference a Worksheet and using a loop (For Each) to change the reference. The same goes for the columns.
Public Sub Sample()
Dim WkSht As Excel.Worksheet
Dim LngCols As Long
Dim LngCol As Long
'This loop will process the code inside it against every worksheet in this Workbook
For Each WkSht In ThisWorkbook.Worksheets
'Go to the top right of the worksheet and then come in, this finds the last used column
LngCols = WkSht.Range(WkSht.Cells(1, WkSht.Columns.Count).Address).End(xlToLeft).Column
'This loop will process the code inside it against every column in the worksheet
For LngCol = 1 To LngCols
'If the first cell contains a date then we should format the column
If IsDate(WkSht.Cells(2, LngCol)) Then
'Set right to the bottom of the sheet
WkSht.Range(WkSht.Cells(2, LngCol), WkSht.Cells(WkSht.Rows.Count, LngCol)).NumberFormat = "dd/mmm/yyyy"
End If
Next
Next
End Sub
Hopefully that has all made sense, this does work on the premise that the header row is always row 1 and there are no gaps in the columns, but these are separate issues you can approach when you're ready to.

Related

Excel Macro To Advance Date

I have a ton of excel sheets that each have 3 excel workbook tabs. On the last one there will be a ton of data but one column will be a date column with a bunch of different dates underneath. The date format will be MM/DD/YYYY. I need to advance each date ahead by 4 years.
I imagine that I will need to select the correct workbook, search for the particular column, and then loop to iterate through each value underneath that column to advance it, but the day itself needs to stay the same. For example, if its 10/05/2017, it needs to be 10/05/2021. Any suggestions or help would be great. Thank you in advance.
Thank you for the help, I realize I wasn't very helpful at all with my question. I'm very new to VB script and excel macros in general. I hadn't gotten how to search for the column itself as I would like it find the column no matter what the column value is (possibly search for a cell that says "Date" through the entire sheet?, I was just trying to add the 4 years to start with and couldn't find the function I needed. This is what I had from what I derived and seems like this is very wrong ha.
Do Until IsEmpty(ActiveCell)
Set ThisCell = ActiveCell
ThisCell = DateAdd("yyyy", 4, ColumnValueHere)
' Step down 1 row from present location.
ActiveCell.Offset(1, 0).Select
Loop
You'll be wanting the DateAdd function
Try something like this:
Sub AddDates()
Dim lastRow as integer
Dim theSheetImWorkingOn as worksheet
Dim theColumnNumberForTheDates as integer
theColumnNumberForTheDates = 5 ' change this to be the column number you want
Set theSheetImWorkingOn = Sheets("Put your sheet name here")
lastRow = theSheetImWorkingOn.Cells(1000000, theColumnNumberForTheDates ).End(xlUp).row
For x = 2 to lastRow ' assuming your data starts on row 2
theSheetImWorkingOn.Cells(x, theColumnNumberForTheDates) = DateAdd("yyyy", 4, theSheetImWorkingOn.Cells(x, theColumnNumberForTheDates))
Next x
End Sub

Excel - Conditional macro / VBA script

I'm trying to automate a report that for a customer and I'm a bit stuck with one of the hurdles that needs to overcome, I have some ideas but am new to VB programming.
The requirement is to copy a range of cells from one sheet to another, but the destination needs to change depending on the current date. Using a general example I'm trying to achieve the following:
If the date is the 1st of the month, the destination range is B2:F3, if it is the 2nd then the destination range is B4:F5, if the 3rd then destination is B6:F7....... if the 31st then the destination is B62:F63, the source ranges are static.
I figured I could probably achieve this by writing a huge script which contained an IF statement for each day of the month, but I was hoping I could be a bit smarter and use variables to assign the row references at the beginning of the script then just sub them back into the select/copy statements.
Absolutely you can.
Dim x as Integer
Dim daymonth as Integer
Dim rw as String
daymonth = CInt(Format(date, "d"))
x = daymonth * 2
rw = CStr(x)
Now you can use range like:
Range("D" & rw & ":F" & CStr(x + 1))
Just an example. Then since the number is constant between the two ranges just add that number to x and use it in the range.
You may want following subroutine.
Sub copyDataDependOnDatte()
Dim today As Date, dayOfToday As Integer
Dim sWS As Worksheet, dWS As Worksheet
'set two worksheets to variables
Set sWS = Worksheets("source") 'Worksheet which has data to be copied
Set dWS = Worksheets("destination") 'Worksheet which is used to record data of days.
' get day of today
today = Now() 'get date of today
dayOfToday = Day(today) ' get day of today
Range(sWS.Cells(2, 2), sWS.Cells(3, 6)).Copy 'copy B2:F3 of worksheet "source"
dWS.Cells(dayOfToday * 2, 2).PasteSpecial ' paste to worksheet "destination" at place determined by day of today
End Sub
In this code,I assumed following for writing concreat code.
"source" is name of worksheet which contains the data to be copied
"destination" is name of worksheet which records tha data copied from "source" worksheet
Data to be copied is exist at "B2:F3" of worksheet "source"
Please change worksheets' names to real names of your data.
Place of data to be copied is described as "Range(sWS.Cells(2, 2), sWS.Cells(3, 6))" in the code.
cells(2,2) means cell on 2nd row and 2nd column, i.e. "B2".
Cells(3,6) means cell on 3rd row and 6th column, i.e. "F3".
Plese correct place to fit your data.

VBA. Comparing values of columns names in two separate worksheets, copy nonmatching columns to third worksheet

So, I've explored a few answered VBA Questions, but I'm still stuck. I have three sheets "By_Oppt_ID", "Top_Bottom" and "Non_Top_Bottom". The first two have a large amount of columns each with a unique name. Now there are some columns in By_Oppt_ID that aren't in "Top_Bottom". So I want to compare each column name in By_Oppt_ID to every column name in "Top_Bottom", and if the column name isn't found, copy that column name and all the rows beneath it, to a third worksheet "Non_Top_Bottom".
So Here's what I have:
Sub Copy_Rows_If()
Dim Range_1 As Worksheet, Range_2 As Worksheet
Dim c As Range
Set Range_1 = Workbooks("Complete_Last_Six_Months_Q_Results.xlsx").Sheets("Top_Bottom")
Set Range_2 = Workbooks("Complete_Last_Six_Months_Q_Results.xlsx").Sheets("By_Oppt_ID")
Application.ScreenUpdating = False ' Stays on the same screen even if referencing different worksheets
For Each c In Range_2.Range("A2:LX2")
' Checks for values not in Range_1
If Application.WorksheetFunction.CountIf(Range_1.Range("A1:CR1"), c.Value) = 0 Then
' If not, copies rows to new worksheet
' LR = .Cells(Row.Count, c).End(xUp).Row
c = ActiveCell
Sheets("By_Oppt_ID").Range("Activecell", "ActiveCell.End(xlDown)").Copy Destination:=Workbooks("Complete_Last_Six_Months_Q_Results.xlsx").Sheets("Non_Top_Bottom").Range("A1:A6745")
Set rgPaste = rgPaste.Offset(0, 1) 'Moves to the next col, but starts at the same row position
End If
Next c
End Sub
I've compiled this many ways and keep getting a series of errors: Subscript Out of Range/ Method "Global_Range" Failure. What am I doing wrong?
If you are going to have this code within the same workbook every time, try using
ThisWorkbook.Sheets("Top_Bottom")
instead of
Workbooks("Complete_Last_Six_Months_Q_Results.xlsx").Sheets("Top_Bottom")
replicate that through your code and see if that fixes the problem.
What do you mean by c = Activecell? Do you mean to say c.activate?
You might then also want to change the next line to
Sheets("By_Oppt_ID").Range(Activecell, ActiveCell.End(xlDown)).Copy Workbooks("Complete_Last_Six_Months_Q_Results.xlsx").Sheets("Non_Top_Bottom").Range("A1")

Excel: Use values in a sheet as index to list in a different sheet and replace values in the first sheet

I have an XL file with some data to be manipulated. I think I will need to use a VB script to do this - but perhaps there is a simpler way with a formula. Just the same, could someone point out BOTH ways of achieving the following?
I have a column of numeric values (ID) in Sheet 1.
I want to use each ID as an index to lookup a list in Sheet 2.
Sheet 2 has two columns
First column is the index and Second column is the Text String
e.g.
1 Apple
2 Orange
3 Pear
What I want is to replace the column of IDs in sheet 1 with the looked up text string from Sheet 2!
Thats all...
Please help!
Not a tough situation there. Here are some solutions...
With VBA:
I know you said you're a little new with VB so I tried to explain each line as I went along. Also, the code is free-handed so forgive me if I left an error in there somewhere.
Sub replaceData()
dim i as integer, j as integer 'These are just some variables we'll use later.
dim sheetOne as worksheet, sheetTwo as worksheet, myWb as workbook
dim myData as string, myId as string
set myWB = excel.activeworkbook 'These three lines set your workbook/sheet variables.
set sheetOne = myWB.worksheets("Old Data")
set sheetTwo = myWB.worksheets("New Data")
for i = 1 to sheetTwo.usedrange.rows.count 'This loops through the rows on your second sheet.
myId = sheetTwo.cells(i,1).value 'This assigns the value for your id and the data on your second sheet.
myData = sheetTwo.cells(i,2).value
for j = 1 to sheetOne.usedrange.rows.count 'This loops through the rows on your first sheet.
if sheetOne.cells(j,1).value = myId then 'This checks each row for a matching id value.
sheetOne.cells(j,1).value = myData 'This replaces that id with the data we got from the second sheet.
end if
next j
next i
end sub
With an Excel formula:
Place the following formula in cell C1 of the first worksheet (the
sheet with the IDs you will be replacing). **Note that you will
have to replace the "InsertSheetTwoNameHere" portion with the name
of your second sheet (don't remove those single quotes though). Also
note you will need to replace the "1000" with the number of the last
used row in sheet two.
=vlookup(A1,’InsertSheetTwoNameHere’!$A$1:$B$1000,2,FALSE)
Next simply drag the handle on the cell that makes it copy itself
(whatever the heck it's called) all the way down to the end of your
range.
Next, copy those cells and then paste them over the IDs using the
Values Only setting.
Hope this helps and good luck.

Excel VBA programming [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I am a complete beginner in excel and got an assignment today to be completed by tomorrow . I would be really grateful if someone can help me out in this .
I have a sheet which has the following table :
The first table is the master , from which i need to get the data and represent it the form of separate tables using marco-VBA . Would appreciate any help to achieve this using macro .Thanks.
Say the master table has n columns , so I need to form n-1 separate tables where each table will have 2 columns the first column will always be the first column of the master table and the second column will be (n+1)th column from the master table for the nth table . Example - 1st table will have 2 columns (1st column of master table and 2nd column of master table ) , likewise 2nd table will have 2 columns (1st column of master table and 3rd column of master table ) , so on and so forth ....
I will be adding to this answer over the next hour or so. The idea is for you to start with the early blocks of code while I develop later blocks. Edit I have now completed the answer except for any extra explanations you might seek.
I agree with RBarryYoung: you do not provide enough information to allow anyone to provide you with a complete solution. Also, if you are trying to learn VBA, giving you the solution will not help in the long term.
I would normally agree with djphatic: the macro recorder is very useful for learning the VBA that matches user operations but the macro recorder will not give you much of the VBA you need for this task.
I am curious who has given you this assignment when you are clearly not ready for it.
I cannot read your image so I created a worksheet which I named "MasterTable" and loaded it with data so it looks like:
Your comments imply that this table may change in size so the first task is to identify its dimensions. There are many different ways of identifying the dimensions of a table; none of which work in every situation. I will use UsedRange.
Copy the following into a module:
Option Explicit
Sub SplitTable1()
Dim UsedRng As Range
With Worksheets("MasterTable")
Set UsedRng = .UsedRange
Debug.Print UsedRng.Address
Debug.Print UsedRng.Columns.Count
Debug.Print UsedRng.Rows.Count
End With
End Sub
There is no time to give full explanations of everything I will show you but I will try to explain the most important points.
Option Explicit means every variable must be declared. Without this statement, a misspelt name will automatically declare a new variable.
Debug.Print outputs values to the Immediate window which should be at the bottom of the VBA Editor screen. If it is not there, click Ctrl+G.
Dim UsedRng As Range declares a variable UsedRng of type Range. A range is a type of Object. When you assign a value to an object, you MUST start the statement with Set.
Running this macro will output the following to the Immediate window:
$A$1:$H$6
8
6
I will not be using UsedRng.Address or UsedRng.Columns.Count but I wanted you to understand what the UsedRange is and how it can be used.
Add this macro to the module:
Sub SplitTable2()
Dim CellValue() As Variant
Dim ColCrnt As Long
Dim RowCrnt As Long
With Worksheets("MasterTable")
CellValue = .UsedRange.Value
For RowCrnt = LBound(CellValue, 1) To UBound(CellValue, 1)
Debug.Print "Row " & RowCrnt & ":";
For ColCrnt = LBound(CellValue, 2) To UBound(CellValue, 2)
Debug.Print " " & CellValue(RowCrnt, ColCrnt);
Next
Debug.Print
Next
End With
End Sub
Dim CellValue() As Variant declares a dynamic array, CellValue, of type Variant. () means I will declare the size of the array at run time.
CellValue = .UsedRange.Value sets the array CellValue to the values within the UserRange. This statement sets the dimensions of CellValue as required.
CellValue becomes a two dimensional array. Normally the first dimension of an array would be the columns and the second the rows but this is not TRUE when the array is loaded from or to a range.
With a one dimensional array, LBound(MyArray) returns the lower bound of the array and UBound(MyArray) returns the upper bound.
With a two dimensional array, LBound(MyArray, 1) returns the lower bound of the first dimension of the array and LBound(MyArray, 2) returns the lower bound of the second dimension.
This macro outputs the following to the Immediate window.
Row 1: Column 1 Column 2 Column 3 Column 4 Column 5 Column 6 Column 7 Column 8
Row 2: R1C1 R1C2 R1C3 R1C4 R1C5 R1C6 R1C7 R1C8
Row 3: R2C1 R2C2 R2C3 R2C4 R2C5 R2C6 R2C7 R2C8
Row 4: R3C1 R3C2 R3C3 R3C4 R3C5 R3C6 R3C7 R3C8
Row 5: R4C1 R4C2 R4C3 R4C4 R4C5 R4C6 R4C7 R4C8
Row 6: R5C1 R5C2 R5C3 R5C4 R5C5 R5C6 R5C7 R5C8
This second macro demonstrates that I can load all the values from the worksheet into an array and then output them.
Add this macro to the module:
Sub SplitTable3()
Dim ColourBack As Long
Dim ColourFont As Long
With Worksheets("MasterTable")
ColourBack = .Range("A1").Interior.Color
ColourFont = .Range("A1").Font.Color
Debug.Print ColourBack
Debug.Print ColourFont
End With
End Sub
Run this macro and it will output:
16711680
16777215
For this answer, these are just magic numbers. 16777215 sets the font colour to white and 16711680 sets the background or interior colour to blue.
For the last macro, I have created another worksheet "SplitTables".
Add this macro to the module:
Sub SplitTable4()
Dim CellValue() As Variant
Dim ColDestCrnt As Long
Dim ColourBack As Long
Dim ColourFont As Long
Dim ColSrcCrnt As Long
Dim RowDestCrnt As Long
Dim RowDestStart As Long
Dim RowSrcCrnt As Long
With Worksheets("MasterTable")
' Load required values from worksheet MasterTable
CellValue = .UsedRange.Value
With .Cells(.UsedRange.Row, .UsedRange.Column)
' Save the values from the top left cell of the used range.
' This allows for the used range being in the middle of the worksheet.
ColourBack = .Interior.Color
ColourFont = .Font.Color
End With
End With
With Worksheets("SplitTables")
' Delete any existing contents of the worksheet
.Cells.EntireRow.Delete
' For this macro I need different variables for the source and destination
' columns. I do not need different variables for the source and destination
' rows but I have coded the macro as though I did. This would allow the
' UsedRange in worksheet "MasterTable" to be in the middle of the worksheet
' and would allow the destination range to be anywhere within worksheet
' "SpltTables".
' Specify the first row and column of the first sub table. You will
' probably want these both to be 1 for cell A1 but I want to show that my
' code will work if you want to start in the middle of the worksheet.
ColDestCrnt = 2
RowDestStart = 3
' I use LBound when I do not need to because I like to be absolutely
' explicit about what I am doing. An array loaded from a range will
' always have lower bounds of one.
For ColSrcCrnt = LBound(CellValue, 2) + 1 To UBound(CellValue, 2)
' Create one sub table from every column after the first.
'Duplicate the colours of the header row in worksheet "MasterTable"
With .Cells(RowDestStart, ColDestCrnt)
.Interior.Color = ColourBack
.Font.Color = ColourFont
End With
With .Cells(RowDestStart, ColDestCrnt + 1)
.Interior.Color = ColourBack
.Font.Color = ColourFont
End With
RowDestCrnt = RowDestStart
For RowSrcCrnt = LBound(CellValue, 1) To UBound(CellValue, 1)
' For each row in CellValue, copy the values from the first and current
' columns to the sub table within worksheet "SplitTables"
.Cells(RowDestCrnt, ColDestCrnt).Value = _
CellValue(RowSrcCrnt, LBound(CellValue, 2))
.Cells(RowDestCrnt, ColDestCrnt + 1).Value = _
CellValue(RowSrcCrnt, ColSrcCrnt)
RowDestCrnt = RowDestCrnt + 1
Next RowSrcCrnt
ColDestCrnt = ColDestCrnt + 3 ' Advance to position of next sub table
Next ColSrcCrnt
End With
End Sub
This is the real macro. All previous macros have served to demonstrate something. This macro does what I think you want.
Come back with questions. However, I do not know what time zone you are in. It is 23:00 here. I will be going to bed in about an hour. After that questions will be answered tomorrow.
Take a look at the macro recorder within Excel. What you are looking to achieve looks like using VBA to perform simple copy and pastes on specific columns within a table. If you turn the macro recorder on and produce the first table by copying and pasting the variable and estimate columns then hit stop, you can view the code producing by viewing the Visual Basic Editor (Ctrl+F11).
You may find these links of some use:
http://www.automateexcel.com/2004/08/18/excel_cut_copy_paste_from_a_macro/
http://www.techrepublic.com/blog/10things/10-ways-to-reference-excel-workbooks-and-sheets-using-vba/967