Date Sequence using VBA - vba

SITUATION
I have a sequence of date serial numbers, for example:
42519, 42526, 42533, 42540, 42547, 42554
in cells
B2, C2, D2, E2, F2, G2
respectively.
Eventually there will be 52 date serial numbers, each one representing a Weekly Invoice Date.
You will notice that each one has been incremented by 7 in a previous macro, which presented no problems.
OBJECTIVE
I need to convert these date serial numbers into a format "dd-mmm-yy", using VBA mentioned in Method 2 below (as opposed to copying formulas manually).
So let's say the first date number is 42519 in cell B2.
Method 1.
This method which converts Date Serial Number 42519 to "dd-mmm-yy" format presents no problem to me but is long winded and involves formula copying manually:
Using expression:
Range("B3")="=TEXT(B2,""dd-mmm-yy"")" ' returns 29-May-16 in cell B3
I can even use the expression:
Range("C3")="=TEXT(B2+7,""dd-mmm-yy"")" 'returns 05-Jun-16 in cell C3
Method 2.
This has me stumped and I'm coming up against a brick wall. It was my idea to do something like the following and if I can get this to work I can go ahead and use a loop to generate 52 dates in a row of 52 cells (C3, D3, etc in the format "dd-mmm-yy", each one incremented by 7 days over the period of a year):
Sub sbNumToText_01()
Dim intAdd7 As Integer
intAdd7 = 0
Dim lngSerialDate As Long
lngSerialDate = Range("C2").Value
MsgBox lngSerialDate + intAdd7 'returns 42526, as expected
Range("C3") = "=TEXT(lngSerialDate + intAdd7,""dd-mmm-yy"")"
End Sub
Instead of cell C3 displaying "05-Jun-16", cell C3 displays #Name? and the mini drop down error menu on the left of cell C3 says "The formula contains unrecognised text".
Can any of you out there please explain how to use the TEXT function incorporating variables? Or any other solution along these lines.

Your problem is with the line
Range("C3") = "=TEXT(lngSerialDate + intAdd7,""dd-mmm-yy"")"
If you look at the formula in cell C3 after running the macro, you'll see it contains
=TEXT(lngSerialDate + intAdd7,"dd-mmm-yy")
But lngSerialDate and intAdd7 are VBA variables, not Excel names, so they are meaningless in a worksheet formula and that's why you see the error. What you want to do is convert the sum of those variables to a number before placing it in the worksheet function:
Range("C3") = "=TEXT(" & lngSerialDate + intAdd7 & ",""dd-mmm-yy"")"

Related

Clone columns, but formulas need to be shifted too - with VBA

I have a cell (A1) which conatins a number, ie. A1 = 4. This means, that I have to clone 4 times a column from a sheet.
It would be very easy, but the trick is, that the cloned columns cells may contain formulas too, which should be shifted by the number of the clone. For the better understanding here is an example:
If the columns contains =A1, the first clone should contain =B1, the second one =C1 and so on.
The copy script, without shifting:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$A$1" Then
For i = 0 To Target
ActiveWorkbook.Sheets("Sheet1").Columns(3).Copy Destination:=Sheets("Sheet1").Columns(i) 'Columns(3) is the column that I am cloning
Next i
End If
End Sub
How should I solve this problem?
If you have a formula (=A1 for example) then the column is automatically shifted, if you want a different behaviour, use $ in front of the column or row:
If you write =$A1, then the column will always stay the same but the row can change
If you write =A$1, the column will change but the row will stay the same
If you write = $A$1 both the column and row will stay the same
Here's my example: In A1 i use the formula =A2. I entered 5 into A2 so A1 shows 5 as well. Now i ran this code:
Dim i As Integer
For i = 1 To 4 Step 1
Cells(1, 1).EntireColumn.Copy Destination:=Cells(1, i).EntireColumn
Next i
Now B1 has the formula =B2, C1 has =C2 and D1 has =D2
If you wouldn't want the formula to change, enter =$A$2 into A1
Hope this helps somehow

Return values from other workbook

Have a question about formula which will resolve my issue.
In my main workbook I need to compare data from two sources.
One of the columns must retrieve data(amounts) from other workbook.
I want formula which will search for all amounts in column G and will skip all blank cells. Tried to use VLOOKUP, INDEX and SMALL functions but no effect.
Each day amounts are different and I need to match them in main file and find exeptions.
Any ideas?
How about an array formula such as the following?
=INDEX($G$2:$G$20,SMALL(IF(($G$2:$G$20)=0,"",ROW($G$2:$G$20)),ROW()-1)-ROW($G$2:$G$20)+1)
The formula would have to be placed into cell I2 as an array formula (which must be entered pressing Strg + Shift + Enter). Then you can drag down the formula to get all the other values.
It doesn't have to be in column I but it has to be in row 2 because this formula get's the n-th Number from the list which is not = 0. The n-th place is (in this formula) row()-1. So for row 2 it will be 2-1=1 and thus the 1st number. By dragging down the formula you get the 2nd, 3rd, etc. number. If you start with the formula in cell I5 instead then it would have to be adjusted to be as follows:
=INDEX($G$2:$G$20,SMALL(IF(($G$2:$G$20)=0,"",ROW($G$2:$G$20)),ROW()-4)-ROW($G$2:$G$20)+1)
You could loop through the column and store each value >0 in an array and then compare or you loop through the column and compare directly...
something like:
Dim i as Integer = 0
Foreach value in Maintable
Do
If otherworkbook.cells(i,7) = value Then '7 for G
do your stuff
End If
i = i + 1
While i < otherworkbook.rows.count
Next
I think that could be the right approach

convert two number to a range

I am going create a macro to convert two number to a range, e.g.
On excel cell A1 and A2, I input integer 1 and 5 respectively. The output will look like:
A3 1
A4 2
A5 3
A6 4
A7 5
How can I do that?
You can accomplish this without even using macros :)
in A3 type your first number.
On the Home tab go to the Editing section > Fill > Series...
Choose to have your series populated in Columns. Choose a stop value of 20 (or whatever)
Click OK
Now you will have a series of numbers 1-20 going down starting in Cell A3.
You can change your step value so that each number is incremented by 1, or 2 or 3 or whatever. You can also fill in rows instead of columns.
If you need it more automated than that just do all of that while recording a macro and see what it does then change the VBA to suit you more specific needs/come back here with some code to get advice on.
The Below COde will read the Content from the A1 and A2. According to the range it will display the result in the A series only.
enter code here
For i = Cells(1, 1) To Cells(1, 2)
Cells(1, i + 2) = i
Next i

How can I count the rows with data in an Excel sheet?

I am trying to count the number of rows in a spreadsheet which contain at least one non-blank value over a few columns: i.e.
row 1 has a text value in column A
row 2 has a text value in column B
row 3 has a text value in column C
row 4 has no values in A, B or C
The formula would equate to 3, because rows 1, 2, & 3 have a text value in at least one column. Similarly if row 1 had a text value in each column (A, B, & C) this would be counted as 1.
With formulas, what you can do is:
in a new column (say col D - cell D2), add =COUNTA(A2:C2)
drag this formula till the end of your data (say cell D4 in our example)
add a last formula to sum it up (e.g in cell D5): =SUM(D2:D4)
If you want a simple one liner that will do it all for you (assuming by no value you mean a blank cell):
=(ROWS(A:A) + ROWS(B:B) + ROWS(C:C)) - COUNTIF(A:C, "")
If by no value you mean the cell contains a 0
=(ROWS(A:A) + ROWS(B:B) + ROWS(C:C)) - COUNTIF(A:C, 0)
The formula works by first summing up all the rows that are in columns A, B, and C (if you need to count more rows, just increase the columns in the range. E.g. ROWS(A:A) + ROWS(B:B) + ROWS(C:C) + ROWS(D:D) + ... + ROWS(Z:Z)).
Then the formula counts the number of values in the same range that are blank (or 0 in the second example).
Last, the formula subtracts the total number of cells with no value from the total number of rows. This leaves you with the number of cells in each row that contain a value
If you don't mind VBA, here is a function that will do it for you. Your call would be something like:
=CountRows(1:10)
Function CountRows(ByVal range As range) As Long
Application.ScreenUpdating = False
Dim row As range
Dim count As Long
For Each row In range.Rows
If (Application.WorksheetFunction.CountBlank(row)) - 256 <> 0 Then
count = count + 1
End If
Next
CountRows = count
Application.ScreenUpdating = True
End Function
How it works: I am exploiting the fact that there is a 256 row limit. The worksheet formula CountBlank will tell you how many cells in a row are blank. If the row has no cells with values, then it will be 256. So I just minus 256 and if it's not 0 then I know there is a cell somewhere that has some value.
Try this scenario:
Array = A1:C7. A1-A3 have values, B2-B6 have value and C1, C3 and C6 have values.
To get a count of the number of rows add a column D (you can hide it after formulas are set up) and in D1 put formula =If(Sum(A1:C1)>0,1,0). Copy the formula from D1 through D7 (for others searching who are not excel literate, the numbers in the sum formula will change to the row you are on and this is fine).
Now in C8 make a sum formula that adds up the D column and the answer should be 6. For visually pleasing purposes hide column D.
You should use the sumif function in Excel:
=SUMIF(A5:C10;"Text_to_find";C5:C10)
This function takes a range like this square A5:C10 then you have some text to find this text can be in A or B then it will add the number from the C-row.
This is what I finally came up with, which works great!
{=SUM(IF((ISTEXT('Worksheet Name!A:A))+(ISTEXT('CCSA Associates'!E:E)),1,0))-1}
Don't forget since it is an array to type the formula above without the "{}", and to CTRL + SHIFT + ENTER instead of just ENTER for the "{}" to appear and for it to be entered properly.

Excel pulling data from certain cells

I have a file that I only want to extract cells B9, B19, B29, etc etc etc in a pattern throughout the entire file. I would preferably like it to be extracted to a different excel file or someway so that I can do stuff with only those cells in another excel worksheet.
Potentially, I may have several excel files that I may need to do this sort of thing so if there were a way where I had the same format throughout a lot of files that I could always extract cells B9, B19, B29 that would be great. any help appreciated
I looking for syntax if possible
EDIT
Was thinking if I could somehow make an excel IF statement saying if Row has a 9 in it and the row is B then print it somewhere but I want it printed in a column
EDIT 2
I just want column B not A like I mentioned before.
B9, B19,B29,B39 through the whole file
Just in case you want to do it with code:
Sub Test()
'Assumes Sheet1 has your values and Sheet2 will be the data extracted from every row ending in 9
Dim iCounter As Long
Dim newSheetRow As Long
Dim aValue As String
Dim bValue As String
newSheetRow = 1
'Start and nine and increment by 10 till you reach end of sheet
For iCounter = 9 To Sheet1.Rows.Count - 1 Step 10 'NOTE: You may not want to do it by RowCount, but just showing you could
aValue = Sheet1.Range("A" & iCounter)
bValue = Sheet1.Range("B" & iCounter)
Sheet2.Range("A" & newSheetRow).Value = "We were on row: " & iCounter
Sheet2.Range("B" & newSheetRow).Value = aValue
Sheet2.Range("C" & newSheetRow).Value = bValue
newSheetRow = newSheetRow + 1
Next iCounter
MsgBox "Done"
End Sub
You could use the INDIRECT function. It takes a cell reference as a text string and returns the value in that cell. So instead of using
=data!a9
to get the value in sheet "data" in cell a9, you use
=indirect("data!a9")
You can also use r1c1 notation, like this:
=indirect("data!r9c1",false)
From there you can use the ROW and COLUMN functions to go in steps of 10:
=INDIRECT("data!r"&-1+10*ROW()&"c"&COLUMN(),FALSE)
If you put this formula in A1 of your output sheet and then copy and paste it down and across, it will give you the values in data!A9, data!A19, data!A29,... in cells A1, A2, A3... Depending on how you want your output arranged, you might have to modify the cell reference string.
Depending on how often you want to do this depends on how you need to do it, if it's a one of them some simple excel commands might help.
e.g.
In Cell C1 put the following:
=MOD(ROW(),10)
then replicate this down to the bottom of your data. the command will return the numbers 1 through to 0. You can then filter the data on column C where value is 9 then select the visible rows and copy the data to a new sheet.
ROW() ' this returns the ROW number of cell the command is in.
MOD(number, divisor) ' this basically divides one number by the other and returns the remainder. so row 9 / 10 = 0 remainder of 9, row 19 / 10 = 1 remainder of 9.
Hope this helps.