I have a huge list, which I have to work on each day. I want to change my reference columns data from number to text so it enables me to do some advanced filtering and referencing futures. I don't want to add any new column and for instance, use Text() function in excel as this range is same in different files I have to concatenate and link. I am just wondering if it is possible to do that in place with a VBA code or not. I tried:
selection=selection.text
or doing some paste special efforts with ', empty cells and converting to array back and forth but not succeded. Any idea? I also don't want to do a loop as I need to this effort for several files which I can't manipulate their structure or change them with my weak laptop each time every day!
Regards,
M
You may want to use built-in Excel functionality Text-to-columns.
If you want it automated using VBA, try this:
With Sheet1
.Range("B1", "B4").TextToColumns Destination:=.Range("B1"), _
DataType:=xlDelimited, _
FieldInfo:=Array(1, 2)
End With
Above converts all numbers in the range B1:B4 in sheet1.
The FieldInfo argument identifies the conversion.
We use Array(1,2) which means we want to convert column 1 to text.
Check Text to columns functionality to understand it further. HTH.
This should help you out. It converts a a range of values into text format
Sub Convert_To_Text()
Dim vData As Variant
vData = Range("A1:D1")
Range("A1:D1").NumberFormat = "#"
Range("A1:D1") = vData
End Sub
Based on #l42 answer and point here is what I was needed... and came to
Sub NumbtoText()
If Not ActiveSheet.FilterMode Then Selection.TextToColumns _
DataType:=xlDelimited, _
FieldInfo:=Array(1, 2)
End Sub
Thanks
Related
I am currently trying to create a macro for Excel in which a column containing certain values (numbers basically) will be displayed in a new column in a normalized way (highest number = 1, lowest number = 0).
Usually, I would just use the formula:
=(J2-MIN($J$2:$J$XXX))/(MAX($J$2:$J$XXX)-MIN($J$2:$J$XXX))
However, as the length of the column is dynamic and will change for each set of values, I cannot enter a value for XXX.
Now, I found out how to have a dynamic range (e.g.: numRows = Range(Selection, Selection.End(xlDown)).Rows.Count) but I did not manage to merge both functions.
I found a thread already in this site about normalization of data but I think it was a bit of a different story and this one here should be simpler.
I would appreciate any help! As I just started working with macros (2h ago) I would also appreciate if this will be in simple language.
EDIT:
First of all, thanks for the quick reply!
I naively tried making it work with this code:
Sub Normalize_TEST()
'
' Normalize_TEST Makro
'
'
Range("A1").Select
numRows = Range(Selection, Selection.End(xlDown)).Rows.Count
Range("K2").Select
ActiveCell.FormulaR1C1 = "=(("J2")-MIN($J$2:$J$numRows$))/((MAX($J$2:$J$numRows$)-MIN($J$2:$J$numRows$))
Range("K2").Select
Selection.AutoFill Destination:=Range(Cells(2, 11), Cells(numRows, 11))
End Sub
But it is not working and I get an error message ("error of compiling").
I just realize now that you are absolutely right, I don't even need VBA. Your line of =(J2-MIN($J:$J))/(MAX($J:$J)-MIN($J:$J)) works fine. I wasn't aware that with $j:$J it realizes to not include empty cells.
I simply used this code now for cell K2 and then did a VBA autofill function for the rest.
I think this can be closed.
Thank you #tigeravatar for your super quick help!
I have to columns with exported numbers, which are stored as text.
I tried to convert those data to numbers with this code.
Sub FormatColumns()
Columns(9).NumberFormat = "0"
Columns(10).NumberFormat = "0"
End Sub
It has done the job correctly (or it seems so), but I am still not able to work with those data as with numbers, but Excel tell me, that it is stored as number.
But when I verify it via formula =ISTEXT(), it always shows me TRUE
Could you help me with it, please? All tutorials and advices, which I've found on Google was via Formating cells or =VALUE(), but VALUE fucntion doesnt work for me, it shows me #VALUE.
Thank you in advance!
Another solution is:
Sub Macro1()
Range("A:A").Select 'Range of values you need converted
For Each Cell In Selection
Cell.Value = (Cell.Value * 1)
Next
End Sub
A non-vba equivalent solution is to have a "1" entered in a cell, copy that cell, select the range you would like converted to numbers, right click and press Paste Special -> Multiply.
This will leave all values in that range as numbers without changing the format. Tested with ISTEXT.
Make sure your settings also match with commas replacing decimals otherwise it may continue to have issues.
you must replace "," ~~> "."
Sub FormatColumns()
With Columns("i:j")
.Replace ",", "."
.NumberFormat = "#,###.00"
End With
End Sub
Check entire relevant region is set to Number format first.
Selection the relevant region and do a global replace of for nothing ("space" to "leave empty"). Then depending upon your locale try a global replace of , to ..
Next enter 1 in a spare cell, copy that cell, select the entire relevant region and Paste Special, Option, Multiply.
If that does not work switch . back to , and repeat the Paste Special.
Its the comma, needs to be . so 405,90 = 405.90
Converting numbers stored as text to numbers via Macro
Sub macro()
Range("F:F").Select 'specify the range which suits your purpose
With Selection
Selection.NumberFormat = "General"
.Value = .Value
End With
End Sub
Hilight the numbers you with to "fix" and run:
Sub fixNumbers()
With Selection
.NumberFormat = "General"
.Value = .Value
End With
End Sub
I'm a complete novice at macros but I've had trouble finding the exact solutions I need, and more trouble combining them. I get this raw data report which needs a couple of changes before I can input it into our master data set for reporting. These things need to happen (please refer to the picture):
The date needs to be expressed in the formation "mmm-yy". I've tried to add "01/" to make "01/04/2017" (I'm Australian so this is the 1st of April), but for some reason it automatically changes it to 04/01/2017. Ultimately, I need 04/2017 to go to Apr-17 for all data in the column
"Medical Div" change to "Medical" and "Mental Health Div" change to "Mental Health" - i've already sorted a macro for this, but not sure how to combine it with another macro for the other functions I'm wanting.
If anyone can help providing code or links to good resources which will allow me to perform all these functions at once with one macro that would be great.
Thanks
This can easily be done with Power Query instead of VBA. Power Query is a free add-in from Microsoft for Excel 2010 and 2013 and built into Excel 2016 as "Get and Transform". Conceptually, the steps are:
Load the data
insert a new column with a formula that combines the text "1/" with the column Month-Year
change the type of the new column to Date
remove the old Month-Year column
select the Division column
replace " Div" with nothing
Save the query
When new data gets added to the original data source, just refresh the query. All this can be achieved by clicking icons and buttons in the user interface. No coding required.
Well, for point 2, how about recording a macro and using Find and Replace twice?
This should combine them into a macro for you. Then you can copy paste that elsewhere.
As for the date, Excel has an predisposition to convert to US format. Try this first (assuming "Month-Year" column is B)
Range("B2") = DateValue(Range("B2"))
Then apply formatting later.
Private Sub mySub()
Dim myRng As Range
Dim r As Range
Dim LastRow As Long
Dim mySheet As Worksheet
Dim myFind1, myFind2 As Variant
Dim myReplace1, myReplace2 As Variant
'This will get the number of rows with value in the sheet
LastRow = Sheets("Sheet1").UsedRange.Rows.Count
'This is for the first find and replace. It will search all cells with exact value of "Medical Div" in the sheet and change it to "Medical".
myFind1 = "Medical Div"
myReplace1 = "Medical"
'This is for the second find and replace. It will search all cells with exact value of "Mental Health Div" in the sheet and change it to "Mental Health".
myFind2 = "Mental Health Div"
myReplace2 = "Mental Health"
'This will loop through the entire column with the date that needs to have the format mmm-yy. It will convert the 04/2017 to date format first before making it Apr-17.
With Sheets("Sheet1")
Set myRng = Sheets("Sheet1").Range("A2:A" & LastRow)
For Each r In myRng
r.Value = CDate(r.Value)
Next r
End With
myRng.NumberFormat = "mmm-yy"
'This will loop through the active worksheet and apply the find and replace declared above.
For Each mySheet In ActiveWorkbook.Worksheets
mySheet.Cells.Replace what:=myFind1, Replacement:=myReplace1, _
LookAt:=xlWhole, SearchOrder:=xlByRows, MatchCase:=False, _
SearchFormat:=False, ReplaceFormat:=False
mySheet.Cells.Replace what:=myFind2, Replacement:=myReplace2, _
LookAt:=xlWhole, SearchOrder:=xlByRows, MatchCase:=False, _
SearchFormat:=False, ReplaceFormat:=False
Next mySheet
End Sub
Here is a code that you could try.
It will change the date format of the column with Month-Year to
"Apr-17" regardless of the current date format.
It will also find and replace the Medical Div and Mental Health Div
to "Medical" and "Mental Health".
You will need to change the range to suit your needs. I have set the column for the month-year to column A. You must change it to column B if that is where your dates are.
This is my data before running the macro:
Here is my data after running the macro:
I have a spreadsheet that is used to import data to a database each week.
The data has to be formatted a particular way for it to import correctly.
I want to use VBA to format the data rather than it be a manual process.
This code changes the data to specific names when the XL workbook is re-opened:
Option Explicit
Private Sub Workbook_Open()
'course name changes
Columns("G:G").Select
Selection.Replace What:="Course Name", replacement:="New Course Name", _
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:= _ False, ReplaceFormat:=False
I repeat this code for each new name. Is there a more concise way of writing this that uses less text? Possibly a way that lets me list all the course names in an array as key value pairs, this way it would be easier to maintain. Thanks
Rather than going through a list of find/replace strings, I think it would be better to use a dictionary structure and loop through each of the cells in your range (Column G) once and evaluate if the phrase is in the dictionary.
A find/replace on a column on a list of phrases is going to be very expensive because each search will go through every value in the range. If you have 1,000 phrase substitutions and 1,000,000 rows, you better go get a sandwich because it's going to be a while.
Looping through the range using a collection is better but still not as good as a dictionary. A dictionary search is O(1), compared to a standard collection/list search which can be O(n). This will be very significant for non-matches, where the collection approach would have you go through every item in the collection before discovering there is no match -- a dictionary knows right away if there is a match and if so, what it is.
Here is an example of how that would work on column G:
Sub ReplacePhrases()
Dim dict As New Dictionary
Dim row, lastRow As Long
Dim replace As String
dict.Add "Course Name", "New Course Name"
dict.Add "VBA, 2nd Edition", "VBA 3rd Edition"
lastRow = ActiveWorkbook.ActiveSheet.UsedRange.Rows.Count
For row = 1 To lastRow
replace = dict(Cells(row, 7).Value2)
If replace <> "" Then
Cells(row, 7).Value2 = replace
End If
Next row
End Sub
The dict.Add lines could be replace by iterating through a list of cells in another worksheet, lines from a file, rows from a database or whatever else you deem appropriate.
I thought I'd be able to figure this out based off an analysis of similar code we had written for something else, but code isn't my forte.
Diving into VBA without guidance has proved to be too daunting for me to proceed.
Forgive my terminology if I use the wrong language, I'm happy to learn and be corrected.
This shouldn't be difficult for someone that knows what they're doing, I just don't at all.
I'm trying to create a macro enabled workbook that does the following:
Open "Data.csv" from a folder called "Data" in the same directory as the macro. We'll call this workbook A - wbA.
Insert a column on wbA after Column C titled "Group Image Name." This Column D is where we want data to end up.
Open "Groups.csv" from a folder called "Groups" in the same directory as the macro. We'll call this workbook B - wkB.
(This next part needs to be a loop that starts at C1 on wbA and proceeds down the column until the end of the spreadsheet)
Copy value from selected cell in Column C on wbA
Search Column C on wbB for copied value. When found, move selection over to corresponding cell in Column A. (If C2, then A2)
Copy contents of the column A value from wbB to column D cell on wbA that corresponds to the original starting point on wbA.
Basically in plain language: Search for Column C contents from wbA on Column C of wbB. When found, move to Column A of same cell # on wbB, copy contents, and paste into cell # of Column D on wbA that corresponds to cell # of starting point from Column C.
I hope that's clear; please feel free to ask for more details if necessary. Thanks for anyone's help in advance!
Here is my terrible code I'm working with at the moment:
Sub OpenDataAddGroupImageTitleColumn()
ChDir "C:\[RealCodeHasCorrectFilepath..]\Desktop\TEST"
Workbooks.Open Filename:="C:\[RealCodeHasCorrectFilepath..]\Desktop\TEST\DATA.csv"
Columns("D:D").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Cells.Select
Cells.EntireColumn.AutoFit
Range("D1").Select
ActiveCell.FormulaR1C1 = "Group Image Title"
Range("C2").Select
'Variables for storing Row, Column Location, and Value here
Dim GROUPNAME As String
Dim RowLocationX As Long
Dim ColumnLocationZ As Integer
GROUPNAME = ActiveCell.Value
RowLocationX = ActiveCell.Row
ColumnLocationZ = ActiveCell.Column
Workbooks.Open Filename:="C:\[RealCodeHasCorrectFilepath..]\Desktop\GROUPS.csv"
Columns("C:C").Select
Selection.Find(What:="GROUPNAME", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
End Sub
The current snag I can't figure out after much googling is this: Is it possible to search for my variable GROUPNAME using the Find/Replace feature? Or should I be taking a different approach using something involving copying to clipboard?
The first problems that I see are:
1) You don't put functions in the middle of sub routines. If you want a function, you put it on its own as such:
Sub MySub()
'Do Stuff
x = myFunction()
debug.print x
End Sub
Function MyFunction() As String
'Do Stuff
MyFunction = "Test"
End Function
2) The code you have provided won't compile for reason 1 and also because you have ended the Sub with "End Function" instead of End Sub. Try running the code and you will get error messages. Then you can research the error message and try to fix it. Further, if you don't get error messages, you can step through the code to make sure it is working the way you intend it to.
3) The very first line isn't going to work. You need to use the ENTIRE path of the file, even if it is in the same folder as the file you currently have open. There are ways to get the directory of the file you currently have open (google will surely show you many of them), and you could just append the filename to the directory of the file you have open.
4) You want a loop, but you haven't put in any looping structions. Google "Excel VBA loop through cells" and you can find many examples to use.
5) I think the biggest issue that you are having is that you are overwhelmed because you are trying to do everything all at once. I would suggest solving one problem at a time and then putting the code together. For instance, you want to open two files. Start by writing code just to open one file. Then try to get a value out of the file into the open workbook. Then open another file. Then get data out of that file. Then test looping through cells in the current workbook and checking for desired criteria and pasting the results if they match. Then combine all of these things into coherent code.
Nobody writes efficient code the first time they try, so even if you end up with really long code that isn't efficient, you'll learn a lot and have something. Even experienced programmers can get stuck or write code that doesn't work the first or even tenth time. If you get stuck, ask a specific question about a specific error message or specific issue that you can't resolve.