I have range of cells in date format, formatted as dd.mm.yyyy, like this:
05.10.1993
05.10.1993
05.10.1993
05.10.1993
and I want to convert this range of cells to text format, using VBA, but without iterating each cell in range (as it is slow for large range).
I used this code:
Set rSel = Selection
aDate = rSel.Value
rSel.NumberFormat = "#"
rSel.Value = aDate
So I assign selected range to intermediate array, then convert the range to text format and assign the array back to selected range.
Result is this text:
5/10/1993
5/10/1993
5/10/1993
5/10/1993
and I wonder where did format conversion took place, as if I debug.print for example aDate(1,1) I get expected 05.10.1993 value? Or how can I instruct format in simple snippet I posted so that I get expected text as a result?
In your code, instead of aDate=rSel.Value, try this:
aDate = Application.Text(rSel.Value2,rSel.NumberFormatLocal)
Note
The following range properties are relevant to this example:
.Value returns a variant (number/date/string/boolean/error) with dates in VBA date format.
.Value2 returns a variant (number/string/boolean/error) with dates converted to serial numbers.
.Text returns a string containing the formatted value, this applies to individual cells only.
.NumberFormat returns regional formats in US format (eg entering 1/2/3 in a cell gives m/d/yyyy)
.NumberFormatLocal returns regional formats in local format (eg in European locale d/m/yy)
Here's something that I posted on my blog. It uses a loop in one direction, but should be a lot faster than your loop attempts. It uses a trick of Selecting a new cell every so often, to account for this bug described by Charles Williams.
Sub NumberToStringWithFormat(rng As Excel.Range)
Dim Texts() As String
Dim i As Long, j As Long
'This might prevent "###" if column too narrow
rng.EntireColumn.AutoFit
'Can't use variables in Dim
ReDim Texts(1 To rng.Rows.Count, 1 To rng.Columns.Count)
For i = 1 To rng.Rows.Count
'Charles Williams' fix for slow code with Text
If i Mod 1000 = 0 Then
rng.Range("A1").Offset(i).Select
End If
For j = 1 To rng.Columns.Count
Texts(i, j) = rng.Cells(i, j).Text
Next j
Next i
'# is the Text format
rng.NumberFormat = "#"
rng.Value2 = Texts
End Sub
Related
I have an excel file with four columns: name, surname, address, area.
There are a lot of rows.
Is there a way to concatenate all the values of every single row in a variable, using vba?
I need a variable that should contain something like this:
(name1, surname1, address1, area1); (name2, surname2, address2, area2); (name3, surname3, address3, area3)...
If you have the following data in your worksheet
Then the following code will read the data into an array …
Option Explicit
Public Sub Example()
Dim RangeData() As Variant ' declare an array
RangeData = Range("A1:D5").Value2 ' read data into array
End Sub
… with the following structure:
Alternatively you can do something like
Public Sub Example()
Dim DataRange As Range
Set DataRange = Range("A2:D5")
Dim RetVal As String
Dim Row As Range
For Each Row In DataRange.Rows
RetVal = RetVal & "(" & Join(Application.Transpose(Application.Transpose(Row.Value2)), ",") & "); "
Next Row
Debug.Print RetVal
End Sub
To get this output:
(name1, surname1, address1, area1); (name2, surname2, address2, area2); (name3, surname3, address3, area3); (name4, surname4, address4, area4);
.. is there a way to write the result like a sort of list that shows all the values of the cells of the range?
Yes, there is. In addition to PEH's valid answers and disposing of Excel version MS365 you might also use
Dim s as String
s = Evaluate("ArrayToText(A2:D5, 1)") ' arg. value 1 representing strict format
resulting in the following output string:
{"name1","surname1","address1","area1";"name2","surname2","address2","area2";"name3","surname3","address3","area3";"name4","surname4","address4","area4"}
Syntax
ARRAYTOTEXT(array, [format])
The ARRAYTOTEXT function returns an array of text values from any specified range. It passes text values unchanged, and converts non-text values to text.
The format argument has two values, 0 (concise default format) and 1 (strict format to be used here to distinguish different rows, too):
Strict format, i.e. value 1 includes escape characters and row delimiters. Generates a string that can be parsed when entered into the formula bar. Encapsulates returned strings in quotes except for Booleans, Numbers and Errors.
Thank you for your answers, suggestions, ideas and hints. I am sorry if my question was not so clear, all the solutions you added were perfect and extremely elegant.
In the end I found a way - a dumber way in comparison to all the things you wrote - and I solved with a for statement.
I did like this:
totRow = ActiveSheet.UsedRange.Rows.Count
For i = 1 To totRow
name = Cells(i, 1)
surname = Cells(i, 2)
address = Cells(i, 3)
area = Cells(i, 4)
Example = Example & "(" & name & ", " & surname & ", " & address & ", " & area & "); "
Next i
Range("E1").Value = Example
It works (it does what I wanted to do), but I noticed a little limit: if the rows are a lot I can't keep the whole text in the variable.
I have a spreadsheet with many columns for each month in the project timeline and each header is in mmm-YY format (like May-20 for 5/1/2020). I'd like to add some more features that act on date values, but when I use DATEVALUE on a cell that has a value of 'May-20', it calculates to "5/20/2021". I believe I have the cell format for the headers correctly set to Number>Date>Mon-Year style, so I'm not sure why excel is misinterpreting the header values.
Is there a way I can get excel to recognize that "May-20" means 05/01/2020?
Use:
=--("1-"&A1)
Where your text is in A1.
You can format the cells as Custom Format --> mmm-yy It will appear as May-20 in the cell, but will have the value 5/20/20 (I'm assuming the day doesn't matter here).
This will however mess up your existing dates. If you need to get them to the proper values you can use this:
Dim i As Long
Dim lr As Long
Dim mth As String
Dim yr As String
With ActiveSheet 'Use a real sheet name
lr = .Cells(.Rows.Count, 2).End(xlUp).Row 'I used column B here
For i = 1 To lr
mth = Split(.Cells(i, 2).Value, "-")(0) 'I used column B here
yr = Split(.Cells(i, 2).Value, "-")(1)'I used column B here
Cells(i, 2).Value = DateValue("01 " & mth & " " & yr) 'I used column B here
Next i
End With
You may want to test it first by not modifying in place.
I want to convert a date in a cell to the date function so it is a formula. How do I get the date (using VBA), any date, say, 13 Jun 2020 to =DATE(2020, 6, 13) using variables for the year, month, and day. My code I have tried but won't work. The activecell shows 13-Jun-2020 as a date but appears in the function box as 13/06/2020
Sub ConvertDateToDateFunction()
Dim mvDay, mvMth, mvYr As Integer
mvDay = Left(ActiveCell, 2)
mvMth = Mid(ActiveCell, 4, 2)
mvYr = Right(ActiveCell, 4)
ActiveCell.Value = "=DATE(mvYr, mvMth, mvDay)"
End Sub
You have two problems. Here is the solution to the smaller one. The code below would do what you intend. It would convert a text string in the ActiveCell to a function of similar value and insert it in the cell below the ActiveCell.
Sub ConvertDateToDateFunction()
' if you don't say what it's supposed to be it'll be a Variant
Dim mvDay As String, mvMth As String, mvYr As String
mvDay = Left(ActiveCell.Value, 2)
mvMth = Mid(ActiveCell.Value, 4, 2)
mvYr = Right(ActiveCell.Value, 4)
ActiveCell.Offset(1).Formula = "=DATE(" & mvYr & "," & mvMth & "," & mvDay & ")"
End Sub
It's not entirely easy to insert a date as a text string in Excel because Excel will try to recognize a date for a date. Observe that any part of a string is a string, not an integer.
Now about your much bigger problem which is that you don't understand how Excel handles dates. It is such a big problem because you are trying to create a date in Excel in various ways and you run into all sorts of trouble. Read up on the subject here.
To give you a taste of what you will learn: what you see displayed in a cell isn't what the cell contains. There might be a formula in it and you see a number. And there might be a date and you see a string. What you see is determined by the cell's format. I think Chip Pearson's article will cover that topic. If you need to know more, look for "Cell formatting" on the web.
Your macro won't work because the date is a "real date" and not a string.
Try the following to convert the contents of cells containing a real date to a formula which will return the same date:
Option Explicit
Sub dtToFormula()
Dim R As Range, C As Range
Dim vDateParts(2)
Set R = [a1:a10]
'Set R = ActiveCell 'or Selection whatever range you want to convert
For Each C In R
If IsDate(C) And Not C.HasFormula Then
vDateParts(0) = Year(C.Value2)
vDateParts(1) = Month(C.Value2)
vDateParts(2) = Day(C.Value2)
C.Formula = "=DATE(" & Join(vDateParts, ",") & ")"
End If
Next C
End Sub
The main problem started when I wanted to "convert to number" by the green triangle (I know I can do it by hand, but there are a lot of cells like that and in the future I only want to use code).
So I wanted to do it by code, and I came across with this code that helps, but I have a problem with the number format which removes the decimal numbers.
Sub Valor3()
Dim LastRow As Long, i As Long
LastRow = Sheets("Hoja3").Range("A" & Rows.Count).End(xlUp).Row
'Sheets("Hoja3").Range("A1:A" & LastRow).NumberFormat = "# ##0,00"
For i = 1 To LastRow
If Val(Sheets("Hoja3").Range("A" & i).Value) <> 0 Then _
Sheets("Hoja3").Range("A" & i).Formula = _
Val(Sheets("Hoja3").Range("A" & i).Value)
Next i
End Sub
I've been trying many formats but none of them seems to help.
It might be because here we use the comma as a decimal separator and there is no miles separator.
What number format would help me?
The issue is that you use Val function in combination with a non-us-english decimal separator, which is not a proper solution to your issue.
The Val function recognizes only the period ( .) as a valid decimal separator. When different decimal separators are used, as in international applications, use CDbl instead to convert a string to a number.
Source: Microsoft documentation Val function.
Since the Val function does not convert a text into a value but extracts
The Val function only works with a dot . as decimal separator.
Example:
Val("2.55") 'will return 2.55 as number
Val("2,55") 'will return 2 as number (because it cuts off all text and the comma is not considered as decimal separator)
To get rid of the green triangle and convert a number that is saved as text into a real number properly, use the following:
Option Explicit
Public Sub ConvertNumberAsTextIntoRealNumber()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Hoja3")
Dim LastRow As Long
LastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
With ws.Range("A1", "A" & LastRow)
.NumberFormat = "# ##0.00" 'set your desired number format
.Value = .Value 'this will in most cases already convert to real numbers.
End With
'But if your numbers are hard coded to text and begin with a `'` you need the following additionally:
Dim iRow As Long
For iRow = 1 To LastRow
With ws.Cells(iRow, "A")
If IsNumeric(.Value) Then 'can the value be interpreted as a number
If .Value <> 0 Then 'is the value not zero
.Value = CDbl(.Value) 'then convert it into a real number
End If
End If
End With
Next iRow
End Sub
I know you are looking for VBA solution, but here's a small Excel trick that you might find useful:
Enter 1 (numeric value) somewhere in the file and copy it:
Select your range (A1:A6) and go to Paste > Paste Special > select Multiply:
The final result is all your text values being converted to numbers:
The same trick will work with other combinations, e.g. Operation: Add while having 0 copied, etc.
I'm looking for a simple Excel VBA or formula that can convert an entire row in Excel from 'number stored as Text' to an actual Number for vlookup reasons.
Can anyone point me in the right direction?
Better Approach
You should use INDEX(MATCH) instead of VLOOKUP because VLOOKUP behaves in an unpredictable manner which causes errors, such as the one you're presumably experiencing.
INDEX ( <return array> , MATCH ( <lookup value> , <lookup array> , 0) )
Using 0 as the last argument to MATCH means the match must be exact
Here is some more in-depth information on INDEX(MATCH)-ing
Further
Add zero +0 to convert a value to a number.
This can be (dangerously) extended with IFERROR() to turn non-numeric text into a zero:
=A2+0
=IFERROR(A2+0,0)
For the inverse, you can catenate an empty string &"" to force the value to be a string.
Notes
If 0 is not used as the last argument to MATCH, it will find all sorts of unexpected "matches" .. and worse, it may find a different value even when an exact match is present.
It often makes sense to do some extra work to determine if there are duplicates in the MATCH lookup column, otherwise the first value found will be returned (see example).
Help with MATCH comes from here, notably the matching logic the 3rd argument controls.
This should work if you add it before your vlookup or index/match lines:
Sheets("Sheet1").UsedRange.Value = Sheets("Sheet1").UsedRange.Value
I did find this, but does anyone have a formula as well?
Sub macro()
Range("F:F").Select 'specify the range which suits your purpose
With Selection
Selection.NumberFormat = "General"
.Value = .Value
End With
End Sub
http://www.ozgrid.com/forum/showthread.php?t=64027
Try this:
Sub ConvertToNumber()
Application.ScreenUpdating = False
Dim cl As Range
For Each cl In Selection.Cells
cl.Value = CInt(cl.Value)
Next cl
Application.ScreenUpdating = True
End Sub
To use it, simply select the relevant block of cells with the mouse, and then run the macro (Alt+F8 to bring up the dialogue box). It will go through each cell in the selected range and convert whatever value it holds into a number.
I wrote a custom vlookup function that doesn't care about data formats. Put this into a module in VBA and use = VLOOK instead of = VLOOKUP
Public Function VLook(sValue As String, rDest As Range, iColNo As Integer)
' custom vlookup that's insensitive to data formats
Dim iLastRow As Long
Dim wsDest As Worksheet
Set wsDest = Sheets(rDest.Parent.Name)
iLastRow = wsDest.Range(wsDest.Cells(100000, rDest.Column).Address).End(xlUp).Row
If iLastRow < rDest.Row + rDest.Rows.Count Then
For X = rDest.Column To rDest.Column + rDest.Columns.Count
If wsDest.Cells(100000, X).End(xlUp).Row > iLastRow Then iLastRow = wsDest.Cells(100000, X).End(xlUp).Row
Next X
End If
sValue = UCase(Application.Clean(Trim(sValue)))
For X = rDest.Row To iLastRow
If UCase(Application.Clean(Trim(wsDest.Cells(X, rDest.Column)))) = sValue Then
VLookDM = wsDest.Cells(X, rDest.Column + iColNo - 1)
Exit For
End If
Next X
End Function
The easiest way I can think of is using the built-in function =VALUE(TEXT_TO_CONVERT_TO_STRING).