Replace an entire coloumn in excel with a new value automatically - vba

I have VBA code which converts a given specific date format into a normal Date. Is there a way in which I can replace the entire column into my new date format may be by a button click or just using a function.
The code I have is:
Function CONVDATE(myDate) As Date
Dim arr
arr = Split(myDate)
CONVDATE = arr(1) & " " & arr(2) & " " & arr(5) & " " & arr(3)
End Function

Immediately to the right of your data enter:
=TEXT(LEFT(A1,11)&RIGHT(A1,4),"ddd mm dd yyyy")
and double-click the fill handle. Then select, Copy and Paste Special Values over the top.

If you want a VBA solution, and you are happy with your CONVDATE function, you can use something like the following to convert an entire column:
===================================
Option Explicit
Sub CONVALLDATES()
Dim RNG As Range, C As Range
'Next line may change depending on how your range to convert is set up
Set RNG = Range("A1", Cells(Rows.Count, "A").End(xlUp))
'Uncomment next line when debugged.
'application.ScreenUpdating = False
For Each C In RNG
With C
.Value = CONVDATE(C)
'.numberformat = whatever format you want it displayed
End With
Next C
Application.ScreenUpdating = True
End Sub
'---------------------------------------------
Function CONVDATE(myDate) As Date
Dim arr
arr = Split(myDate)
CONVDATE = arr(1) & " " & arr(2) & " " & arr(5) & " " & arr(3)
End Function
====================================
You should add some error checking to ensure the string you are trying to convert is, indeed, in the specific format.

Related

VBA Testing two values, if one is different, copy

I am having a fair amount of trouble with the code below:
Sub TestEmail()
Dim i As Long
Dim LastRow As Long
Dim a As Worksheet
Dim b As Worksheet
Dim strText
Dim ObjData As New MSForms.DataObject
Set a = Workbooks("Book2").Worksheets(1)
Set b = Workbooks("Book1").Worksheets(1)
LastRow = a.Cells(Rows.Count, "A").End(xlUp).Row
For i = 2 To LastRow
If Not IsError(Application.Match(a.Cells(i, 7).Value, b.Columns(3), 0)) And IsError(Application.Match(a.Cells(i, 4).Value, b.Columns(11), 0)) Then
a.Range("D" & i).Copy
ObjData.GetFromClipboard
strText = Replace(ObjData.GetText(), Chr(10), "")
b.Range("K" & ).Value = b.Range("K" & ).Value & " / " & strText
End If
Next i
End Sub
I face two problems, one has me stumped and the other is due to lack of knowledge:
The line after IF is supposed to check if two values (numbers) in both workbooks match, and if two other values (text) don't match. If all true, then it must copy a value from Book2 and add it to a cell in book1.
The problems are:
-The macro doesn't seem to recognise when the values match or not.
-In the last line before "End If", I don't know how to tell excel to copy the text into the cell that didn't match in the second check.
I am sorry if I am not clear enough, this is hard to explain.
I'm hoping one of the experts knows how to make this work.
Thanks in advance
You are using If Not condition 1 And condition 2, so you are saying that if it doesn't match both conditions, Then you run the code. What you want to make are Nested If Statements However, one is If and the other If Not
To copy you are missing the i After "K"&: b.Range("K" & i) = b.Range("K" & i).Value & " / " & strText
The Address of the Cells are inside the Range Function, which in your case would be:
//It is the cell of the email from the first Workbook tou are copying, where you input the column D
a.Range("D" & i).Copy
//Add to Workbook b in column K the value from Cell K#/value copied
b.Range("K" & i) = b.Range("K" & i).Value & " / " & strText
You can also make it like this: b.Range("K" & i) = b.Range("K" & i).Value & " / " & a.Range("D" & i)
This way you are matching lines, so only if the IDs are on the same rows on both Workbooks it will work. If they aren't, you will have to use Nesting Loops or .Find Function
EDIT:
If I understood it, the code below might work if you make some changes for your application, because i didn't have the data to test and columns, etc. Try to implement it.
LastRowa = a.Cells(Rows.Count, "A").End(xlUp).Row
LastRowb = b.Cells(Rows.Count, "A").End(xlUp).Row
For i = 2 To LastRowa
'Address of String to look for
LookForString = a.Worksheets(1).Cells(i, 4) '4 is the COLUMN_INDEX
'Range to look on Workbook a
With a.Worksheets(1).Range("D1:D" & LastRowa) 'choose column to look
'Function .Find String on book a
Set mail_a = .Find(LookForString, LookIn:=xlValues)
If Not mail_a Is Nothing Then
FirstAddress = mail_a.Address
Do ' Actions here
'Range to look on Workbook b
With b.Worksheets(1).Range("K1:K" & LastRowb) 'choose column to look
'Function .Find on Workbook b
Set mail_b = .Find(LookForString, LookIn:=xlValues)
If Not mail_b Is Nothing Then
FirstAddress = mail_b.Address
Do 'Actions
'Verify if two other values (text) don't match
If Not WRITE_MATCH_CONDITION_HERE Then
'No need to verify of they are equal because the .Find function used the same reference
'I will use .Cells with .Row and .Column just to show another way to do it and make it dynamic
b.Cells(mail_b.Adress.Row, mail_b.Adress.Column) = b.Cells(mail_b.Adress.Row, mail_b.Adress.Column).Value & " / " & a.Cells(mail_a.Adress.Row, mail_a.Adress.Column) 'choose columns
End If
Set mail_b = .FindNext(mail_b)
Loop While Not mail_b Is Nothing And mail_b.Address <> FirstAddress
End If
End With
Set mail_a = .FindNext(mail_a)
Loop While Not mail_a Is Nothing And mail_a.Address <> FirstAddress
End If
End With
Next i
End Sub
p.s.: The <> is missing on mail_a.Address <> FirstAddress and mail_b.Address <> FirstAddress, when i posted with

custom made functions in VBA

I have a list of films and their durations in minutes. I wish to create a custom function whereby the user selects the range of durations i.e. one or more cells. The function converts the duration in minutes into " x hours and y minutes form ".
I have created the following function but it does not seem to take more than 1 cell reference at a time.
Function Saikatrealtime(cell As Range) As String
Dim r As String
r = Int(cell.Value / 60) & " hours " & " & " & cell.Value Mod 60 & " minutes "
Saikatrealtime = r
End Function
Sub realtimesof_film()
Dim rng As Range
Dim t As String
s1.Activate
Set rng = Application.InputBox(prompt:=" enter range ", Type:=8)
t = Saikatrealtime(rng)
rng.Offset(0, 2).Value = t
End Sub
Whenever I give a reference to rng as 2 or more cells, it gives the error type mismatch at the line
r = Int(cell.Value / 60) & " hours " & " & " & cell.Value Mod 60 & " minutes "
Can anyone please tell me how I can modify the code so that the function runs across multiple cell references given to rng?
Unless you change the formula to return an array of values, you'll have to modify the subroutine code to reference multi-cell ranges. Adding a loop of the cells within the range will work. Add this to your subroutine:
Dim Cell As Range
For Each Cell In rng.Cells
Cell.Offset(0, 2).Value = Saikatrealtime(Cell)
Next Cell
There is no need for the custom function Saikatrealtime. You can use Format instead. The key is that you have to escape certain letters in the text using a backslash \
Sub realtimesof_film()
Dim rng As Range
Dim c As Range
Set rng = Application.InputBox(prompt:=" enter range ", Type:=8)
For Each c In rng
c.Offset(0, 2).Value = Format(c.Value, "HH \hour\s & MM \mi\nute\s ")
Next
End Sub

excel vba - Using autofilter - can't pass the filtered range to a sub, it keeps passing the entire sheet range

I can't seem to figure this one out. I have a function and a sub where I call the function to get the unique values (from column N (text values)) from the range I've already selected from the autofilter. Somehow, the range keeps being the entire sheet range and not the selected.
Function UniquesFromRange(rng As Range)
Dim d As Object, c As Range, tmp
Set d = CreateObject("scripting.dictionary")
For Each c In rng.Cells
tmp = Trim(c.Value)
If Len(tmp) > 0 Then
If Not d.Exists(tmp) Then d.Add tmp, 1
End If
Next c
UniquesFromRange = d.Keys
End Function
Sub mainSub()
For Each key In fCatId.Keys
With wshcore
llastrow = wshcore.Range("A" & Rows.Count).End(xlUp).Row
.AutoFilterMode = False
.Range("A1:N" & llastrow).AutoFilter
.Range("A1:N" & llastrow).AutoFilter Field:=1, Criteria1:=fCatId(key)
lwmin = WorksheetFunction.Subtotal(5, Range("H:H"))
lwmax = WorksheetFunction.Subtotal(4, Range("H:H"))
'This does not work, I want to get the unique values from column N
'that are already in the filtered range. So far this shows
'all the values in the column not only the ones already filtered.
varArray = UniquesFromRange(Range("N:N"))
'I've also tried this:
'varArray = UniquesFromRange(Range.Cells)
'Debug.Print fCatId(key) & " - " & key & " " & lwmin & "-" & lwmax & fData(key) & " - " & Join(varArray, vbNewLine)
End With
Next key
Application.ScreenUpdating = True
End Sub
any suggestions?
Instead of
varArray = UniquesFromRange(Range("N:N"))
use
varArray = UniquesFromRange(Range("N1:N" & llastrow).SpecialCells(xlCellTypeVisible))
In response to the additional question asked in the comments, you could copy varArray to another sheet (assumed to already exist, and being referred to by the object wsOutput, and output to be written to column A) as follows
Dim r as Integer
For r = LBound(varArray) To UBound(varArray)
wsOutput.Cells(r, 1).Value = varArray(r)
Next

countif outputting "true" or "false" rather than number vba

I have been trying to code a countif function into a loop, however, I am having a little trouble with the outputs. Instead of reading a number when the computation occurs, the function keeps outputting "true" or "false". Maybe there is an error in my code, but I have used many countif functions in the past without experiencing a problem such as this. As you can see below, I tried to write the function in two different ways, but both either didn't work or outputted "true" or "false".
Please Help.
Sub CorrectSets()
Dim Cell As Range
Range("B100000").End(xlUp).Select
LastRow = ActiveCell.Row
For Each Cell In Range("S2:S" & LastRow)
StartTime = Cell.Offset(0, -12)
Shift = Cell.Offset(0, -14)
SortedOp = Cell.Offset(0, -17)
DOW = Cell.Offset(0, -5)
'Cell.Value = CountIF(E2:E & LastRow, Shift, N2:N & LastRow ,DOW, B2:B & LastRow,SortedOp, G2:G & LastRow, " < " & StartTime)
Cell.Value = "=CountIF(E2:E" & LastRow & ", " & Shift & ", N2:N" & LastRow & "," & DOW & ", B2:B" & LastRow & "," & SortedOp & ", G2:G" & LastRow & ", " < " " & StartTime & ")"
Next Cell
If you want to put a countif() Formula in Cell then:
Cell.Formula = "=CountIF(E2:E &...............
If you want to put the formula's result in Cell then:
Cell.Value = Application.Worksheetfunction.CountIF(E2:E &....................
You should use
Cell.Formula = "=CountIFs..."
or
Cell.Value = WorksheetFunction.CountIfs...
See official documentation.
Plus:
To find the last row containing data in a column (B in this case) use
Dim ws as Worksheet
Set ws = ActiveSheet
Dim LastRow as Long
LastRow = ws.Range("B" & ws.Rows.Count).End(xlUp).Row
ws is a reference to the Worksheet of interest (ActiveSheet in my example).
See this answer.
You'd rather fully qualify your ranges, and avoid using Select unless it is strictly needed.
With the code posted above,
Range("B100000").End(xlUp).Select
might not be needed.
If using Cell.Formula = "=CountIFs...", it might be convenient to use
Dim frm as String
frm = "=CountIFs..."
Cell.Formula = frm
for easier debugging.

Using VLookup in a macro

I'm new to VBA but I'm hooked! I've created a workbook that tracks overtime in 2 week blocks with one 2-week block per worksheet. The macro I'm trying to debug is designed to carry any changes made in a worksheet over to following worksheets. The trick is that the data in one row may be in a different row in following worksheets so I trying to use VLookup in a macro to keep it accurate.
Sub CarryForward()
Dim Answer As String
Answer = MsgBox("This should only be used for a PERMANENT crew change." & vbNewLine & "If you are adding a new person to the list," & vbNewLine & "please use the Re-Sort function." & vbNewLine & "Do you want to continue?", vbExclamation + vbYesNo, "Caution!")
If Answer = vbNo Then
Exit Sub
End If
Application.ScreenUpdating = False
Dim ActiveWorksheet As String
ActiveWorksheet = ActiveSheet.Name
For i = (ActiveSheet.Index + 1) To Sheets("DATA").Index - 1
For x = 5 To 25
Dim a As String
Dim b As String
a = "B" & x
b = "C" & x
ActiveSheet.Range(b).Value = Application.WorksheetFunction.VLookup(a, Sheets(ActiveWorksheet).Range("B5:C25"), 2, False)
Next x
Range("A3").Select
Next i
Sheets(ActiveWorksheet).Select
Application.CutCopyMode = False
Range("A3").Select
Application.ScreenUpdating = True
End Sub
I'm pretty sure it's just a syntax error in the VLookup line of code. A lot of the help posted comes close to what I'm looking for, it just doesn't get me over the finish line.
Any help would be appreciated!
It is a little unclear what you are trying to do, but reading between the lines I think
you want to lookup the value contained in cell named by a?
and put the result on sheet index i?
Also, there is a lot of opportunity to improve your code: see imbedded comments below
Sub CarryForward()
Dim Answer As VbMsgBoxResult ' <-- Correct Datatype
Answer = MsgBox("This should only be used for a PERMANENT crew change." & vbNewLine & _
"If you are adding a new person to the list," & vbNewLine & _
"please use the Re-Sort function." & vbNewLine & _
"Do you want to continue?", _
vbExclamation + vbYesNo, "Caution!")
If Answer = vbNo Then
Exit Sub
End If
Application.ScreenUpdating = False
' Dim ActiveWorksheet As String <-- Don't need this
'ActiveWorksheet = ActiveSheet.Name <-- use object variables
Dim wbActive As Workbook ' <-- don't select, use variables for sheet objects
Dim shActive As Worksheet
Set wbActive = ActiveWorkbook
Set shActive = ActiveSheet
'Dim a As String ' <-- no point in putting these inside the loop in VBA. And don't need these anyway
'Dim b As String
Dim SearchRange As Range
Set SearchRange = shActive.Range("B5:C25") ' <-- Use variable to hold range
Dim shDest As Worksheet
Dim i As Long, x As Long '<-- dim all your variables
For i = (shActive.Index + 1) To wbActive.Worksheets("DATA").Index - 1 ' <-- qualify references
Set shDest = wbActive.Sheets(i)
For x = 5 To 25
'a = "B" & x <-- no need to create cell names
'b = "C" & x
' I think you want to lookup the value contained in cell named by a?
' and put the result on sheet index i?
' Note: if value is not found, this will return N/A. Add an error handler
wbActive.Sheets(i).Cells(x, 3).Value = Application.VLookup(shActive.Cells(x, 2).Value, SearchRange, 2, False)
Next x
'Range("A3").Select
Next i
'Sheets(ActiveWorksheet).Select ,-- don't need these
'Application.CutCopyMode = False
'Range("A3").Select
Application.ScreenUpdating = True
End Sub
I suspect you would want to replace the vlookup statement to be something like
Application.WorksheetFunction.VLookup(ActiveWorksheet.Range(a).value, ActiveWorksheet.Range("B5:C25"), 2, False)
at the moment it looks like you're just doing a vlookup against some strings B5, B6, B7 etc instead of values in those cells