In excel, I have a text string, which contains numbers and text, that I strip the numbers out of with a formula. However, sometimes it is possible that the text string will be blank to begin with so if this happens I use "" to return a blank instead of a 0. When I link this excel sheet to an access database it will not let me format this column as currency because it is picking up the "" as text along with the stripped out numbers as numbers. Any solutions on how to fix this? Is there another way besides "" to make a cell completely blank and not a zero length string?
This is along the lines of the problem I am having:
http://support.microsoft.com/kb/162539
Here is a quick routine that reduces formulas to their values and strips zero length strings to truly blank cells.
Sub strip_zero_length_string()
Dim c As Long
With Sheets("Sheet1").Cells(1, 1).CurrentRegion
.Cells = .Cells.Value
For c = 1 To .Columns.Count
.Columns(c).TextToColumns Destination:=.Cells(1, c), _
DataType:=xlFixedWidth, FieldInfo:=Array(0, 1)
Next c
End With
End Sub
I'm using .CurrentRegion so there can be no completely blank rows or columns within your data block but that is usually the case when preparing to export to a database.
Related
I have a column of cells in excel that have the following formatting: "0000.00"
FYI, the quotes are not part of formatting.
Basically, four digits followed by two decimals. However, when the numbers are like "600", they need to be displayed as "0600.00". However, the list of numbers provided to me are displayed that way through formatting, so if I am trying to VLOOKUP, it can't process it; it sees "600", not "0600.00" that is displayed to me.
I am aware of PasteSpecial Paste:=xlPasteValues, but this pastes "600", not the "0600.00" that is displayed to me. Currently I can achieve such results by copying the values and pasting them into notepad —which suggests to me there is a way to do this— but I'd like to create a macro to do this for me.
Sorry for any redundant explanation, just wanted to avoid getting answers relating to pasting values only, which is not what I am looking for.
As you said, to use VLOOKUP with formatted text as the lookup value, you'll need the value of the cell to match with the value of the lookup value, so you'll have to convert the value in the cell to text with something like this (example for a single cell):
Dim rng As Range
Set rng = Range("A1")
rng.PasteSpecial xlPasteFormulasAndNumberFormats
Dim TextValue As String
TextValue = Format(rng, rng.NumberFormat)
rng.NumberFormat = "#" 'We need this line to turn the cell content into text
rng.Value2 = TextValue
I'm pretty sure no PasteSpecial options will allow you to do what you want in a single operation, so this solution is a workaround that does it in two steps.
Multiple cells case:
I realize that the code above doesn't address the issue of pasting multiple cells, so here's a procedure that can be used to copy the formatted number as text from one range to another:
Sub CopyAsFormattedText(ByRef SourceRange As Range, ByRef DestinationRange As Range)
'Load values into an array
Dim CellValues() As Variant
CellValues = SourceRange.Value2
'Transform values using number format from source range
Dim i As Long, j As Long
For i = 1 To UBound(CellValues, 1)
For j = 1 To UBound(CellValues, 2)
CellValues(i, j) = Format(CellValues(i, j), SourceRange.Cells(i, j).NumberFormat)
Next j
Next i
'Paste to destination by using the top left cell and resizing the range to be the same size as the source range
Dim TopLeftCell As Range
Set TopLeftCell = DestinationRange.Cells(1, 1)
Dim PasteRange As Range
Set PasteRange = TopLeftCell.Resize(UBound(CellValues, 1), UBound(CellValues, 2))
PasteRange.NumberFormat = "#" 'We need this line to turn the cells content into text
PasteRange.Value2 = CellValues
End Sub
It's basically the same idea, but with a loop.
Note that if the formatting is always the same, you could make it a variable and apply it to every values in the array instead of calling .NumberFormat on every cell which inevitably adds a little bit of overhead.
Sidenote
One could ask why I'm not suggesting to use :
SourceRange.Cells(i, j).Text
instead of
Format(CellValues(i, j), SourceRange.Cells(i, j).NumberFormat)
And that would be a very good question! I guess, the fact that .Text can return "###..." when the column isn't sized properly always makes me afraid of using it, but it certainly would look much cleaner in the code. However, I'm not sure what would be better in terms of performance. (Relevant article by Charles Williams)
I have a large amount data in an Excel file. I have over 3000 rows which cross A to CZ columns.
Before I start using the data, I need to trim all of it.
When I use VBA it takes a long time and I get error "Type not match".
Some cells contain space, some contain formula, some contain formula link with another Excel file.
Worksheets("Sheet1").Activate
For Each cell In ActiveSheet.UsedRange.SpecialCells(xlCellTypeConstants)
If cell.HasFormula = False Then
cell.Value = Trim(cell)
End If
Next cell
It want to trim the cells which do not have a formula but it gets the error.
Text-to-Columns, Fixed width, Finish will quickly remove leading/trailing spaces.
dim i as long
with Worksheets("Sheet1")
for i=.cells(1, .columns.count).end(xltoleft).column to 1 step -1
with .columns(i)
.cells.TextToColumns Destination:=.cells(1), DataType:=xlFixedWidth, _
FieldInfo:=Array(0, 1)
end with
next i
end with
BTW, if you want to reduce multiple interim spaces (e.g. data data to data data) to a single space, you need to use Application.Trim(...) not VBA.Trim(...).
Worksheets("Sheet1").Activate
For Each cell In ActiveSheet.UsedRange
If Not IsError(cell) Then
cell = WorksheetFunction.Trim(cell)
End If
Next cell
finally i use this code to ignore the error. i know it is not a good method.
I am new to vba coding (and coding in general) but I have started doing a small macro that transfers values of a csv file into an excel file.
My next step is to remove the quotation marks in each cell. I have tried these lines of codes in my sub:
Dim Table As Range
Dim Cell As Variant
Set Table = Range("A1:currentregion")
For Each Cell In Table
cell.value2 = Replace(cell.value2,""","") *I get a syntax error here*
Next Cell
I know this is very basic but I can't find a solution on the net or using the macro recorder. If anybody could tell me what I am doing wrong and also what code I could use to change the value in a cell that contains a string of numbers into a numeric value?
Thanks!
You don't need to loop through each cell. The Range("A1").CurrentRegion may be operated on as a whole.
With Range("A1").CurrentRegion
.Replace What:="""", Replacement:=vbNullString, LookAt:=xlPart
End With
Note that to look for a single quote (e.g. ") you need 4 quotes in a row. An alternative is Chr(34) as a quote symbol is the 34th ASCII character.
Addendum:
With regard to the second portion of your question, changing text that looks like a number to actual numbers is best done with a quick Text to Columns ► Fixed Width command. Each column would have to be run through individually but this can be accomplished within the .CurrentRegion.
Dim c As Long
With Range("A1").CurrentRegion
.Replace What:="""", Replacement:=vbNullString, LookAt:=xlPart
For c = 1 To .Columns.Count
.Columns(c).NumberFormat = "General"
.Columns(c).TextToColumns Destination:=.Columns(c), _
DataType:=xlFixedWidth, FieldInfo:=Array(0, 1)
Next c
End With
There is the question of what number format the columns were in to begin with. If they were Text (e.g. '.NumberFormat = "#"` then removing the quotes is not going to convert them to true numbers. I've added a reversion to the General number format to accommodate this. If you have existing number formats that you wish to keep, there are more precise ways of reverting the number formats of some of the cells.
Cell.Value2 = Replace(Cell.Value2, Chr(34), "")
There always is a workaround, this one is referencing via character code.
You should dim Cell as Range. Also it's not a very good idea to name a variable using a VBA syntax element. Use MyTable and MyCell instead.
And to set the range better use
Set MyTable = [A1]
For Each MyCell In MyTable.CurrentRegion
...
I'm using VBA to do some further formatting to a generated CSV file that's always in the same format. I have a problem with my For Each Loop. the loop deletes an entire row if there is more than one blank row which can be determined from the first column alone.
Dim rowCount As Integer
For Each cell In Columns("A").Cells
rowCount = rowCount + 1
'
' Delete blank row
'
If cell = "" And cell.Offset(1, 0) = "" Then
Rows(rowCount + 1).EntireRow.Delete
spaceCount = 0
End If
Next
At some point the value in the loop one of the calls does not have a value of "", it's just empty and causes it to crash. To solve this I think that changing the type of the cell to text before that compare would work but I can't figure out how (no intellisense!!!)
So how do you convert a cell type in VBA or how else would I solve the problem?
Thanks.
Use cell.Value instead of the cell.Text as it will evaluate the value of the cell regardless of the formating. Press F1 over .Value and .Text to read more about both.
Be carefull with the statement For Each cell In Columns("A").Cells as you will test every row in the sheet (over a million in Excel 2010) and it could make Excel to crash.
Edit:
Consider also the funcion TRIM. It removes every empty space before and after a string. If in the cell there is a white space " "; it will look like empty for the human eye, but it has a space inside therefore is different than "". If you want to treat it like an empty cell, then try:
If Trim(cell.value) = "" then
As #andy (https://stackoverflow.com/users/1248931/andy-holaday) said in a comment, For Each is definitely the way to go. This even allows for there to be spaces in between lines.
Example code:
Sub ListFirstCol()
Worksheets("Sheet1").Activate
Range("A1").Activate
For Each cell In Application.Intersect(Range("A:A"), Worksheets("Sheet1").UsedRange)
MsgBox (cell)
Next
End Sub
Thanks Andy!
I am going to show a bit of a contrived example, so bear with it.
Our product makes use of CSV files for transitional data, data sent between an Excel user interface, a Java program to manipulate and transfer it to a SQL backend. We have a VBA script that handles all the Excel work in the following order:
Load all 8 CSV files into 8 sheets in a single Excel document. Then iterate over batches of the data doing the following:
'Loop over data:
Dim r As Range
...
r.NumberFormat = "General"
r.Formula = r.Formula
'End loop
This causes the entire sheet to be populated with data from CSV, with number cells to have text appearance and Excel formulas to remain unevaluated. Running r.Formula = r.Formula triggers all the functions to evaluate properly. The only problem is the number formatting.
The CSV files sometimes contain nested CSV. For example, a single cell may contain "1,2,3,15,654" These cells always appear as text. However, there is an edge case, wherein the cells could be pretty print numbers, such as "10,456,345" Excel will convert these numbers into Number cells after evaluating all the functions, and strip out all of the commas. While the 20,000 or so rows in the document are otherwise correct, the 4 or so rows this affects breaks the entire system.
Is there a way to trigger Excel to evaluate the functions from CSV without changing the cell formatting entirely from VBA? Changing formats from CSV to SYLK is not an option, as the Java CSV Generator is handled by a different division.
You could turn formatting to text on all the cells (Cells.NumberFormat="#") then loop over them and use your code on cells which start with '='.
If performance is an issue you should put the worksheet content in an array, work on the array and put it back to the sheet.
If you post more code and sample data people will be able to have a closer look.
EDIT
for example, putting the following values in column A (from A1 to A4) of "Sheet1", with a Text formatting:
13246
13564,4654,4565
654
=A1+A3
and using the following code:
Sub test()
Dim a As Variant
Dim result As Variant
a = Sheets("Sheet1").UsedRange
ReDim result(1 To UBound(a, 1), 1 To UBound(a, 2)) As Variant
For i = 1 To UBound(a, 1)
For j = 1 To UBound(a, 2)
If Left(a(i, j), 1) = "=" Then
result(i, j) = a(i, j)
Else
result(i, j) = "'" & a(i, j)
End If
Next j
Next i
Sheets("Sheet1").Cells(1, 2).Resize(UBound(result, 1), UBound(result, 2)) = result
End Sub
The result is put in column B and is :
13246
13564,4654,4565
654
13900
I have an alternative technique that may be suitable.
I created a worksheet with 26,000 values: strings, numbers, dates, numbers with embedded commas and formulae.
I ran a loop over the above sheet of which the inner code was:
ValueCell = .Cells(RowCrnt, ColCrnt).Formula
If IsNumeric(Replace(ValueCell, ",", "")) Then
.Cells(RowCrnt, ColCrnt).Formula = Replace(ValueCell, ",", "|")
End If
.Cells(RowCrnt, ColCrnt).Formula gives the formula if the cell contains one or the value if it does not. If the value or formula with any commas removed is numeric, I replace any commas with pipes.
With 26,000 cells this took 59 seconds. Does this compare favourable with your extra 45 seconds per 500 rows?
Any values like "1,2,3,15,654" would now be "1|2|3|15|654" but I assume that is not a problem. If you have nested strings such as "ab,cd,ef" they would still contain commas. Perhaps testing for a leading "=" to eliminate formulae and automatically replacing commas in everything else would be a possibility.
The following code took 78 seconds to run against 26,000 cells.
ValueCell = .Cells(RowCrnt, ColCrnt).Formula
If Left(ValueCell, 1) <> "=" Then
.Cells(RowCrnt, ColCrnt).Formula = Replace(ValueCell, ",", "|")
End If
Hope this helps if only to give you new ideas.
I propose an alternative, more straightforward approach:
Have you considered writing to an Excel spreadsheet directly from your Java program, using e.g. Apache POI? Seems to me it would be much more straightforward, less contrived, and less error-prone than this whole formulas-in-a-CSV business.