Problem
While writing this post, I realized what the issue was and fixed it. However, after spending too much time on this, I still would like to know if this is the best way to go about this.
In a worksheet I'm applying a macro to I have a column where some cells contain text, others contain dates (DD.MM.YYYY). Excel automatically aligns text to the left, dates to the right.
I've run into the problem of sometimes having trailing spaces in this column. So I used a for-loop with TRIM to make sure there are no leading or trailing spaces. It worked, but all dates are now aligned to the left, whereas before they were aligned to the right. When I double click into one of those cells and then select another cell, the date snaps back to the right (which is what I want), even though I haven't done anything to the cell.
Fix
It took me way too long to realize (or read attentively) that TRIM is for strings.
I noticed before running the macro: Dates are automatically aligned to the right, but in the ribbon, in "Alignment", there's no option for horizontal alignment selected. If I do so manually and align the dates to the right and then run the macro, the dates stay to the right.
When checking VarType before running the macro, I get 8 for the cells with text and 7 for the cells with dates, as expected. After running the macro, however, I get 8 (meaning string) for both. After double clicking into a cell with date and deselecting it, VarType is 7 again. In the Excel ribbon it always says that it's a Date (before and after the macro), so Excel seemingly doesn't show me what VBA tells me.
My workaround now is this: Before applying TRIM, my macro checks the VarType of the cell and if it is 7, it does nothing since the trailing spaces only have been a problem where users enter text. (Alternatively, I could align the dates right and let TRIM run over all cells)
This is fine, but is there a better way to do this? Does using TRIM on dates have the potential to screw something up? I'm trying to learn something from this.
Code
For good measure, my sample code, with the fix included.
Sub Test()
Dim ws As Worksheet
Dim searchRng As Range
Dim cell As Variant
Set ws = ActiveSheet
With ws
Set searchRng = .Range("A1:A100")
For Each cell In searchRng
If VarType(cell) = 7 Then
'Date -> Do Nothing
Else
cell.Value = WorksheetFunction.Trim(cell.Value)
End If
Next cell
End With
End Sub
For your question, I have do some testing, and my result is quite different compared to you, is it because excel version?
I have a data in A1 by put spacing in front of the date as below:
By executing the following function, the first typename was string, however after remove the spacing it end up typename date, I think it is not necessary to check the type on your solution?
Sub tt()
Debug.Print TypeName(Sheet1.Range("A1").Value)
Sheet1.Range("A1").Value = Trim(Sheet1.Range("A1").Value)
Debug.Print TypeName(Sheet1.Range("A1").Value)
End Sub
So it mean your code can be simplified on the loop as following and still produce the same result, it doesn't matter it is aligned to right:
For Each cell In searchRng
cell.Value = Trim(cell.Value)
Next cell
Related
I'm trying to make a button which on click will print out the value of a cell as a string and not the appearance of the cell itself (if that makes sense) using the .PrintOut method in VBA. That cell is the active cell, whose value I set based on the cell next to it. Here is my code:
Sub Graphic2_Click()
Dim MyNumber as Integer
MyNumber = ActiveCell.Offset(-1, 0) + 1
ActiveCell.Value = MyNumber
ActiveCell.Printout
End Sub
I also tried MyNumber.PrintOut but I get an "Invalid Qualifier" error.
Am I missing out something too simple?
Please, try the next code. It use a temporary 'helper cell' where the format to be pasted (and recuperated after printing out):
Sub Graphic2_Click()
Dim helperCell As Range
With ActiveCell
.value = CLng(Offset(-1, 0)) + 1
Set helperCell = .Offset(1) 'it may be any cell to temporarilly be used
.Copy
helperCell.PasteSpecial xlPasteFormats
.ClearFormats
.PrintOut
helperCell.Copy
.PasteSpecial xlPasteFormats: helperCell.ClearFormats
End With
End Sub
To literally print just the contents of the cell:
Clear number formatting for the specified cell
Autofit column width for that column
Turn off gridlines
Turn off row and column headings
Set print area to the single cell, dismissing any warnings
Print out the active sheet
Each of these are straightforward to do in VBA, and probably straightforward to research on SO anyway.
You may also consider a mechanism to return the changed settings to their initial states afterwards. This would involve pushing (storing) the initial state to a variable or variables first, and popping (restoring) it back afterwards.
Explanation:
The VBA method .PrintOut is something you do to a worksheet, not a cell or its contents. Therefore, to get what you need, you need to set up the worksheet for printing so that the only thing that will appear is the contents of your chosen cell. This is what the above steps do.
For more information about the .PrintOut method, see:
https://learn.microsoft.com/en-us/office/vba/api/excel.sheets.printout
Or, to continue what the OP tried:
You could try something like:
ActiveCell.Formula = Range(ActiveCell.Offset(-1,0)).Value2 + 1
If this does not work, try:
ActiveCell.Formula = Range(ActiveCell.Offset(-1,0).Address).Value2 + 1
Or try these without the + 1 on the end, to verify that the rest of the formula is working the way you want it too. As mentioned, you may get a type mismatch issue causing an error if you don't trap first for whether the referenced cell contains a number.
.Formula in this example is how I am setting the content of the cell, and it can be used even when setting a value not necessarily literally a formula. You could use Value instead if you prefer.
.Value2 is a robust method of extracting the evaluated content of the source cell, as a value instead of as a formula.
The PrintOut method is to print a worksheet, not a range or single cell.
Note: This answer is not tested, as I am not near Excel right now.
Also... it's possible that there could be much simpler ways to do what you are trying to accomplish. Could you provide a bit more detail about the context of what you are trying to do.
After my formulas and macros run, Im looking to highlight the cells in my worksheet that are outputted as a "" (Result of an If Formula).
It is a dynamic range, and I am having difficulty finding a way to change the color of Just the cells with a space. Any ideas would be very helpful.
Dim cell As Variant
For Each cell In Sheets("[Sheet name here]").UsedRange.Columns("U").Cells
If InStr(cell.Value, "") = 0 Then
cell.Interior.ColorIndex = 15
End If
Next cell
End Sub
Then I basically repeated it for column "D", but it takes an unusually long time to complete...
Im thinking i can implement the
=LEN(??)=0 function, but not sure how to do so...
The reason it is running so slow is that you're calling Excel Object for every cell in your range. If column U has 1,000 cells that aren't empty then that is 1,000 calls to the Excel object model.
It is much faster to read the entire range into memory at one time and then process it in memory. This is very easy to do. The code below reads cells A1:A100 but the key difference is that it only calls the Excel Object one time (instead of 100 times).
Dim MyData As Variant
MyData = Range("A1:A100").Value
For your code you would do something like this ...
Dim MyData As Variant
Dim i As Long
MyData = ActiveSheet.UsedRange.Columns("U").Cells.Value
For i = 1 To UBound(MyData)
If (MyData(i, 1) = "") Then
'keep track of which cells need to be colored
End If
Next
If you have a lot of cells that need coloring, you will need to use a "non-contiguous" range selecting in order to perform this with one call to Excel's object model. See this article for more information Using VBA to select non-adjacent range
Thanks all. In this instance, I ended up modifying my formulas to actually generate a space " " instead of a null string, "" as #Scott Craner pointed out.
With a legitimate space, I just achieved the same results using conditional formatting, as #tigeravatar suggested.
Thank you all for the help, I really appreciate it !
im trying to work out a little scheduler in excel to manage my life a little better. I use different cell colors for each event (yellow for work, red for university, etc.). I already have a macro CountColor which counts the occurence of a color in a certain range which works fine (i pretty much copy pasted it from an online solution). I now use the macro to calculate the used time into cells like this:
the cells contain =ColorCount(H5;B2:F15) whereas the interior color of the first argument determines the color to count and the seconds parameter is the range to count the color in. This macro works fine. The last number is just the sum of the above three.
I now however face the problem, that changing the interior color of a cell does not trigger the recalculation of formulars. I created a simple button (not the ActiveX one) and assigned a macro to it:
Public Sub CalcButton_onclick()
Worksheets(1).Range("I13:I16").Calculate
End Sub
but when i click the button (i also tried to recalculate the whole sheet by using Worksheets(1).Calculate) nothing happens. Only when i, for example, change the value int the cell my times get recalculated. My button's macro is definitely executed i tested that by adding Worksheets(1).Cells(20, 20).Value = "Test" after the Calculate call and it changed the value of the given cell properly.
For the purpose of completion, i also add the code of the CountColor macro:
'counts the occurence of the interior color of rColor in rRange
Public Function ColorCount(ByRef rColor As Range, ByRef rRange As Range) As Integer
Dim rCell As Range
Dim lCol As Long
Dim vResult As Integer
vResult = 0
lCol = rColor.Interior.ColorIndex
For Each rCell In rRange
If rCell.Interior.ColorIndex = lCol Then
vResult = 1 + vResult
End If
Next rCell
ColorCount = vResult
End Function
Im not really sure what the problem is but i believe i may have misinterpreted the Calculate method. I only created the 2 macros above. I appriciate any help!
By the way something meta: is this a proper use of a picture in a question? I could not think of a better way to show what i want my output to look like.
Making your colorcount UDF volatile would help (add Application.Volatile) but as you have discovered changing the color or formatting of a cell does not trigger a recalculation so even a volatile UDF will not recalc just on a color change.
If you make your UDF volatile then Range.Calculate should trigger a recalc in Automatic calc mode.
I found the problem myself.
At first i want to thank everyone for their hints and tips. I would propably have needed them after fixing my initial problem and so i had them fixed in advance :)
My problem actually was apparently, that i wanted to declare my spare time as white color. But actually i had several cells which had "no fill color" after coloring every free cell explicitely white it now works with the button. The solution with Worksheet_Change() method in the sheet code did not work unfortunately because a color change is not evaluated as a change in the sheet. Worksheet_SelectionChange() however did the trick with updating when you click on another cell so i do not need the button anymore.
I have an Excel file that looks like this. How would I change the cell formatting so that it looks exactly like it does it the function bar. Instead of 3E-07 --> 0.000003
I don't want to change the decimal places because I only want it to have the number of decimal places it needs so there won't be extra zeroes at the end.
For example because the smallest numbers have 7 decimal places if I change the whole column to seven decimal places numbers like 6E-05 will have two extra zeroes (0.0000600) at the end.
I'm trying to do this on macro because there are a lot of numbers to go through. I can set up the loop myself.
To fix on all columns, follow below steps:-
Click on the symbol mentioned side of A column (That is left side of A)
When you click on that symbol, it will select whole sheet
Double Click on border line between A column & B column
This is fix all your problems on the excel sheet
This number format issue is occurred due to column size.
To fix this type of number format "0.0000600":-
select the Column header (that is A column, B column .. and soon which ever column you need to format)
Right click on the tab
Select "Format Cell"
Click on custom option under Category
under Type field, enter 0.0000000000
Then it fix your format issue.
You have tagged this question with VBA so here are two examples of VBA's .AutoFit method.
For the entire worksheet:
With ActiveSheet 'set this worksheet reference more defintively!
.Cells.EntireColumn.AutoFit
End With
If you have columns that are already the width you want you could test the first 20 rows to see if the .TEXT property is displaying the hash mark (e.g. # or Chr(35)) symbol.
With ActiveSheet 'set this worksheet reference properly!
With .Cells(1, 1).CurrentRegion
For c = 1 To .Columns.Count
For r = 1 To 20 'maybe even .Rows.Count for smaller data grids
If CBool(InStr(1, .Cells(r, c).Text, Chr(35), vbBinaryCompare)) Then
.Columns(c).EntireColumn.AutoFit
Exit For
End If
Next r
Next c
End With
End With
The latter defined the range of cells to work on using the .CurrentRegion property which expands from its origin until it meets a fully blank row and column.
Very basic, and very annoying, I have searched solution for many hours with no help...
Problem: I'm populating Combobox from named range, range is list of times (formatted as time :-), Combo seems fine, drop-down shows my times as they should be, but when selected time is formatted as a decimal number...
Here is the code (ripped down to bare minimum):
Private Sub UserForm_Initialize()
ComboBoxTime.RowSource = "Help!Time"
End Sub
"Help" is name of worksheet containing named range "Time"I have tried formatting different ways with no luck...
ComboBoxTime = Format(ComboBoxTime, "hhmm")
Here is link to sample. http://www.equstom.fi/dateproblem.html
(And yes I need to populate from named range, instead for each loop, and I will set .value with code, Whole document is actually quite complex, but I included just The problem part...)
Try something like this:
Private Sub ComboBox1_Change()
With ComboBox1
.Value = Format(.Value, "hh:mm:ss AMPM")
End With
End Sub
HTH!
Edit
This is what I see when leaving your combo. The time display works OK.
Edit 2
Found the error "invalid property":
You must set "Match Requiered" to FALSE in the combo box. If you consider that it should be "TRUE" you will have to validate by hand ...
The problem is named range I'm using, when values are formatted as time it won't work. I got it to work if values were Text! Problem has something to do with excel being in Finnish and VBA in english...
I added second column next to range which copies text values to this named second range formatted as time. Quick and Dirty! (Thanks for your input Belisarius)