How to put character if there is one digit in cell in VBA Macro? - vba

I would like to ask, how to put character, in this case 0 to cell, if the cell already contains digit in it.
To clarify what do I mean, if on the cell is number 5, I would like to put before the number 5, number 0 to have the result 05.
As far as I know, cell format should be TEXT to avoid automatic Excel correction. But, this question is specific due to several different characters in the cells. In some point I got in the same column different characters in the cells (1, 2, 3, AV, AR, IX etc.).
For example: I would like to select column K, find the numeric characters with one digit (1, 2, 3, -9) and paste there 0 before it to have two space digit like 01, 02, 03, …
Of course, with macro. I know how to put Text format to it, but do not know how to manage the whole macro function to select column K, format whole column as text, find one digit number in the column and paste 0 before it.
Does anybody know how to do that?
Many thanks in advance.

There are 2 solutions:
Format the numbers
Convert numbers to text and format them
1. Format the numbers
The advantage of this solution is that the numbers will still be numbers (not text) but formatted with leading zeros. Therefore you still can calculate with these numbers as before.
Public Sub ChangeNumberFormat()
ThisWorkbook.Worksheets("YourDesiredSheetName").Columns("K").NumberFormat = "00"
'this will keep them numbers but only change the format of them
End Sub
Note that you don't need to do this necessarily with VBA you can just set a user defined cell format 00 for column K (open format cells with Ctrl + 1).
2. Convert numbers to text and format them
If you really need to convert them to text this would be a possible solution. But I really don't recommend that because you cannot calculate with these "numbers" anymore because they are converted to text.
The trick would be to format the number with numberformat first and then convert it to text (see comments in the code).
Option Explicit 'force variable declaring
Public Sub FixLeadingZerosInText()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("YourDesiredSheetName") '<-- change your sheet name here
Dim lRow As Long
lRow = ws.Cells(ws.Rows.Count, "K").End(xlUp).Row 'find last used row in column K
Dim iCell As Range
For Each iCell In ws.Range("K1:K" & lRow) 'loop from row 1 to last used in column K
If iCell.Value < 10 And iCell.Value > -10 Then 'check if it is a one digit number
Dim tmpText As String
tmpText = Format(iCell.Value, "00") 'format the one digit number
iCell.NumberFormat = "#" 'convert number to text
iCell.Value = tmpText 're-write formatted number
End If
iCell.NumberFormat = "#" 'make all other numbers in column K formatted as text too
Next iCell
End Sub

Related

How to sort excel values with numbers in end

I have a macro which reads file names from a folder. The problem is that when file names are in series like A1,A2.....A200.pdf, as in this image:
then it reads in Excel as A1,A10,A100,A101.....A109,A11,A110.....A119,A20, as in this image:
How can I sort this so that the value in Excel comes as same as folder file names, or is there a way I can sort in Excel itself?
You can sort this in Excel with a helper column. Create a new column and calculate the length of your filenames in that "=LEN(A1)". Then use two-level sort to sort your filenames. Data -> Sort: Use length in the first level and the filenames in the second level.
Another option, you can use the RegEx object to extract the Numeric digits "captured" inside the file name.
Option Explicit
Sub SortFileNames()
Dim i As Long
With Sheets("Sheet1") ' replaces "Sheet1| with your sheet's name
For i = 1 To .Cells(.Rows.Count, "A").End(xlUp).Row
.Range("B" & i).Value = RetractNumberwithRegex(.Range("A" & i)) ' call the Regex function
Next i
End With
End Sub
'========================================================================
Function RetractNumberwithRegex(Rng As Range) As String
' function uses the Regex object to substract the Numeric values inside
Dim Reg1 As Object
Dim Matches As Object
Set Reg1 = CreateObject("vbscript.regexp")
With Reg1
.Global = True
.MultiLine = True
.IgnoreCase = False
.Pattern = "[0-9]{1,20}" ' any size numeric string (up to 20 digits length)
End With
Set Matches = Reg1.Execute(Rng.Value2)
If Matches.Count <> 0 Then
RetractNumberwithRegex = Matches.Item(0)
End If
End Function
This is happening ofcourse of because different sorting algorithm in both these cases (Windows Explorer and Excel) Refer to this article if you want to understand.
To solve your problem, one of the ways is to pull out only the numeric part of file names in a different cell (say column B) and then sort based on those numbers.
If I can assume that the pattern of the files names is AXXX.pdf i.e. one letter A, then number, and 4 characters for file extension. You can use this function
=VALUE(MID(A1,2,LEN(A1)-5))
This works by pulling out some number of characters from in between the string. As per assumption, the number starts from 2nd place that's why the second parameter is 2. Then to decide, how many characters you pull, you know that all the characters except 'A' (1 char) and '.pdf' (4 chars) make the number. So, take the lenght of the whole name and reduce 5 characters. You get your number part which you can sort.
This will be your result:
The best way is to change the file names in your Excel list to have leading zeroes. Instead of A19, refer to the file as A019 and it will sort correctly. Convert the file names using this formula in a helper column.
=Left($A2, 1) & Right("000" & Mid($A2, 2, 3), 3)
Note that the 3 zeroes and string lengths of 3 are all related to each other. To create fixed length numbers of 4 digits, just use 4 zeroes and increase both string lengths to 4.
Copy the formula down from row 2 to the end. Copy the helper column, paste Values in place and, when everything is perfect, replace the original column with the helper.
In order to accommodate a fixed number of digits following the number the above formula may be tweaked. The formula below will accommodate 4 extra characters which follow the number, for example ".pdf" (including the period).
=Left($A2, 1) & Right("000" & Mid($A2, 2, 7), 7)

Macro to convert every 9th column into numbers in excel

For some reason, even when I select a column, right click, and format the cells to be numbers, I still get an alert with a green corner in the cell that says that it's a number stored as text. I then highlight the range, click the exclamation point in the yellow box, and convert the range to numbers.
The problem is that I have to do this for hundreds of ranges.
How can I make a macro to highlight a range (e.g. XP2:XP2700) in every 9th column, and convert the entire range to numbers?
This is a follow-up to the OP's previous question, which, I answered.
Load the data into an array typecast it into a number then write it back over the original range.
Sub ConvertToNumber()
Dim x As Long, y As Long
Dim Data
With Worksheets("CPR Test 2013-2015")
For y = 1 To 1582 Step 9
Data = .Cells(2, y).Resize(2699, 1).Value
For x = 1 To UBound(Data, 1)
If IsNumeric(Data(x, 1)) And Not IsEmpty(Data(x, 1)) Then
Data(x, 1) = CDbl(Data(x, 1))
End If
Next
.Cells(2, y).Resize(2699, 1).Value = Data
Next
End With
End Sub

VBA - Copy Formatting of Range to Array

I'm creating a report with multiple columns. What I need is that the columns that show only whole numbers, no decimals, should be rounded to the whole number (so that it not only shows a rounded number, it actually equals a round number). The columns that show the numbers with two numbers after the decimal should not be rounded.
What I can do is:
If c.NumberFormat = "#,##0_);(#,##0)" Then
c.Formula = "=round(" & Right(strFormula, Len(strFormula) - 1) & ",0)"
End If
However, I have the entire report in an array, and I would like to just paste the whole array into the sheet rather than pasting one cell at a time. I would also rather not process and round each cell based on the cell formatting, rather I would like to copy the formatting of the range where the report will go into an array, and work from the array. I believe this will cut a few seconds off the process.
Is there a way to copy the formatting of a range into an array?
Is there a way to copy the formatting of a range into an array?
Focusing on the question as posed, yes, that can be done. Unfortunately, it can't done in a one-liner, in the way that a range's values can be assigned to an array with myArray = Range("A2:F25"), for example. (See, also, brettdj's comment.) Instead, you'd need something like:
Dim rng as Range
Dim formatArray() As String
Dim i as Long, j as Long
Set rng = Range(A2:F20) 'or whatever the range is
Redim formatArray(1 to rng.Rows.Count, 1 to rng.Columns.Count)
For i = 1 to rng.Rows.Count
For j = 1 to rng.Columns.Count
formatArray(i, j) = rng.Cells(i, j).NumberFormat
Next
Next
...
A couple of observations, though:
You actually only need to know the formatting for a single row of the range since, presumably, the number formatting in a column will not change mid-column.
That would simplify the code to:
...
Redim formatArray(1 to rng.Columns.Count)
For i = 1 to rng.Columns.Count
formatArray(i) = rng.Cells(1, i).NumberFormat
Next
...
assuming, for sake of example, that row 1 of the range has the necessary number formats.
I am curious why you would want to modify a formula on the worksheet so that it will round, since you could presumably do the calculation in your code, with rounding, and then write the resulting value back to the sheet for your report.
If you need to apply number formats to the values you are writing to the worksheet (not just modify formulas so that they will produce whole numbers), that can be done to whole columns within the range at once, i.e.,
...
For i = 1 to rng.Columns.Count
rng.Columns(i).NumberFormat = formatArray(i)
Next
...
If you need to convert the results of a cell's formula to a rounded value, you can do that with something like
rng.Cells(2, 5).Value = WorksheetFunction.Round(rng.Cells(2, 5).Value, 0)
to give an example for a single cell. This assumes, of course, that the data feeding into the formula are already in the sheet and that the formula has been recalculated.

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.

VBA: preceding zeros dropped when copied over

I am creating a copy of an Excel file using VBA. In the file, there is a column that includes numbers with preceding zeros. The copy of the file is created, but the data in this column is dropped. I need to keep the values with the preceding zeros. How can I resolve this problem with VBA?
The best way is to pre-format the column as Text by setting Range.NumberFormat to "#". This way, if a user edits the cell, the cell will stay as text and maintain it's leading zeros. Here is a VBA example:
ActiveSheet.Range("C:C").NumberFormat = "#"
Convert each cell in that column to a text field prior to exporting it. That should ensure that every character is retained (and not treated like a number, which is what it sounds like is happening).
An additional possibility is to append an apostrphe to each cell. This will treat all the values as text which is useful when different tabs treat common values as text vs number (ie copied in vs calculated).
This is done by using the Chr() function and assigning it the character code 39('):
For x = 1 to 100
If Sheets(origSheet).Cells(x, "A").Value <> "" Then
Sheets(origSheet).Cells(x, "A").Value = Chr(39) & Sheets(origSheet).Cells(x, "A").Value
End If
Given the accepted answer, it's probably not what you need, but setting a custom number format will also get the preceeding zeroes back into the displayed value.
To show a value with leading zeroes up to 8 digits, for example, set the format to 00000000, then 123 will be displayed as 00000123.
Both the method here and the format-as-text method will result in cell values that will still work in calculations, although horizontal alignment will be different by default. Note also that, for example, concatenating strings to the values will result in differences:
as text: displays 00000123, append "x" to get 00000123x
as number with custom format: displays 00000123, append "x" to get 123x, because it's still really a number.
Probably TMI, though!
This is the code I have created to resolve this issue:
Public Sub Change_10_Digit()
'----------------------------------------------------------------------------
' Change numeric loan number ot a 10 digit text number
' 2010-05-21 by Jamie Coxe
'
' Note: Insure exracted data Column is formated as text before running macro
'----------------------------------------------------------------------------
Dim Lastrow As Long
Dim StartRow As Long
Dim Col As String
Dim RowNum As Long
Dim nCol As String
Dim Loan As String
Dim Digit_Loan As String
Dim MyCell As String
Dim NewCell As String
Dim Cell_Len As Long
Dim MyOption As Long
'----- Set Options -------------------------------------------------------
MyOption = 2 '1 = place data in new column, 2 = Replace data in cell
StartRow = 2 'Start processing data at this row (skip header row)
Col = "B" 'Loan number in this colmun to be changed to 10 digit
nCol = "G" 'New column to place value (option 1 only)
'----- End Option Setings ------------------------------------------------
'Get last row
Lastrow = Range(Col & "65536").End(xlUp).Row
For RowNum = StartRow To Lastrow
'Combined Column and Row number to get cell data
MyCell = Col & RowNum
'Get data in cell
Loan = Range(MyCell).Value
'Change data in cell to 10 digit numeric with leading zeros
Digit_Loan = Format(Loan, "0000000000")
If My0ption = 1 Then
'Option 1 enter value in new cell
NewCell = nCol & RowNum
Range(NewCell).Value = Digit_Loan
Else
'Option 2 replace value in cell
Range(MyCell).Value = Digit_Loan
End If
Next RowNum
End Sub