Copying Values and excluding #N/A cells - excel

I have the below code that copies cells from one excel sheet and pastes special values into a text file.
now from the sheet I'm copying, I have a lot of cells which contain #N/A.
can anyone suggest how to exclude these cells?
thanks
Private Sub CommandButton3_Click()
Dim i As Long
Dim wb As Workbook
Dim NewWB As Workbook
Dim saveFile As String
Dim WorkRng As Range
On Error Resume Next
i = Sheets(1).Range("W158:W" & Range("W158").End(xlDown).Row).Rows.Count
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set wb = ActiveWorkbook
Set NewWB = Application.Workbooks.Add
Thispath = wb.path
wb.Sheets(2).Range("W158:W" & i + 5).Copy
NewWB.Worksheets(1).Range("A1").PasteSpecial Paste:=xlPasteValues
NewWB.SaveAs filename:=Thispath & "\textfile.txt", FileFormat:=xlText,
CreateBackup:=False
NewWB.Close
Application.CutCopyMode = False
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub

The only way i can think of is to do a basic for loop to go through all the cells individually and check for their value
For Each cell In activehseet.Range("W158:W" & i + 5)
With cell
If .Value = "#N\A" Then
Exit Sub
Else
.Copy
'code to paste here
End With
Next cell
This unfortunately would take quite a while to run and would only get longer the larger the size of the database. I would suggest losing any rows/columns that aren't in use to speed this up.
However it is probably the easiest method to fix your problem
It could be possible by using an array but as I am not an expert with array manipulation i couldn't be sure. I'm sure someone a lot smarter than me could help you through that
Hope this helps get you started. Great question!

You can try to wrap your formulas in IFERROR, just select all cells which you want to wrap and run the following macro:
Sub WrapFormulasWIthIFERROR()
Dim Cell As Range
For Each Cell In Selection
If Cell.HasFormula Then
If Left(Cell.Formula, 9) <> "=IFERROR(" Then
Cell.Formula = "=IFERROR(" & Mid(Cell.Formula, 2) & ","""")"
End If
End If
Next
End Sub
If the cell value is N/A, the result will be an empty cell. Just be aware to not select the whole sheet, because it will run forever.

Related

Prevent a MsgBox from a different VBA script from popping up

I have written a script in the workbook that sends a msgbox warning users not to copy and paste cells whenever they do so.
Target.PasteSpecial xlPasteValues
If Application.CutCopyMode = xlCopy Then
MsgBox ("Please do not copy and paste cells. This can cause errors in log sheet")
ElseIf Application.CutCopyMode = xlCut Then
MsgBox ("Please do not copy and paste cells. This can cause errors in log sheet")
End If
Application.CutCopyMode = False
The problem is I have made other scripts assigned to buttons which are used to copy and paste specific cells when the function is called, but I get my own warning message pop up when this happens. Is there a way to prevent the msgbox popping up in these instances?
I have tried;
Application.DisplayAlerts = False
Application.DisplayAlerts = True
But this doesn't seem to work with scripted msgboxes
Don't use copy/Paste method for many reasons.
Slow
Less Reliable, especially with pastespecial
Is causing you issues in this case.
Try instead to make values or formulas = source values or formulas.
Example:
Copy/Paste:
Sub Copy_Paste()
Dim srcRG As Range 'Source Range
Dim dstRG As Range 'Destination Range
Set srcRG = Sheet1.Range("B2:B6")
Set dstRG = Sheet1.Range("C2:C6")
'Copy all
srcRG.Copy dstRG
'Or Copy Values
srcRG.Copy
dstRG.PasteSpecial xlPasteValues
'Or Copy formulas
srcRG.Copy
dstRG.PasteSpecial xlPasteFormulas
End Sub
Becomes:
Sub Values_Formulas()
Dim srcRG As Range 'Source Range
Dim dstRG As Range 'Destination Range
Set srcRG = Sheet1.Range("B2:B6")
Set dstRG = Sheet1.Range("C2:C6")
'Copy values
dstRG.Value = srcRG.Value
'Or Copy formulas
dstRG.Formula = srcRG.Formula
'Or Copy cell color
dstRG.Interior.Color = srcRG.Interior.Color
End Sub
Won't throw error.
At the Bottom of this link you can find a list of properties you can copy this way

Do while loop on visible cells only after autofilter?

I am stuck on a code where I apply a filter and then have to copy paste data from filtered rows to another sheet. But for some reason the code is not doing anything at all. I have applied an if condition but that is not working, it would be better if the condition was visible cells condition. Basically I want to apply filter>> then I want to copy cell in column 2 to another worksheet and perform calculation>> then copy calculated value in cell in column 7
Sub DOCFairshare()
Set ws = ThisWorkbook.Sheets("Final Orders") 'Setting worksheet in variable
ws.Activate
ws.AutoFilterMode = False 'Removing all filters
ActiveSheet.Range("$A$2:$EL$1561").AutoFilter Field:=50, Criteria1:= _
"DOC Planning Required" 'DOC Filter applied
i = 1
Do Until IsEmpty(Cells(i, 2))
If Cells(i, 50) = "DOC Planning Required" Then
Cells(i, 7).Copy
Worksheets("DOC Fairshare").Range("A3").PasteSpecial Paste:=xlPasteValues
Sheets("DOC Fairshare").Calculate
Worksheets("DOC Fairshare").Range("D11:U11").Copy
Worksheets("Final Orders").Cells(i, 7).PasteSpecial Paste:=xlPasteValues
Debug.Print Cells(i, 2)
End If
' Debug.Print Cells(i, 2)
i = i + 1
Loop
End Sub
I recommend to look at and use SpecialCells method in VBA help. I think it is very usefull.
In your case using like this example.
Range("A1:A10").SpecialCells(xlCellTypeVisible).Copy Range("C1")
It copies only visible cells to C1 from range A1-A10. I think more elegant then make loop and check if cell is visible and then copy which I used to do.
You do not say anything... I asume that my understanding should be correct. The code also assumes that on the second row there are not headers. If they exist, the line Set rngDocPl = ws.Range("AX2:AX1561")... should be adapted to Set rngDocPl = ws.Range("AX3:AX1561")....
Please, try the next code. It will stop after each iteration and shows in Immediate Window (Ctrl + G being in VBE) the value in G:G before calculations and after. Is it what you need? I cannot imagine what formulas you have in Worksheets("DOC Fairshare") and I cannot test anything:
Sub DOCFairshare()
Dim ws As Worksheet, wsDoc As Worksheet, rngDocPl As Range, cel As Range
Set ws = ThisWorkbook.Sheets("Final Orders") 'Setting worksheet in variable
Set wsDoc = Worksheets("DOC Fairshare") 'is this sheet in the same workbook?
ws.AutoFilterMode = False 'Removing all filters
ws.Range("$A$2:$EL$1561").AutoFilter field:=50, Criteria1:= _
"DOC Planning Required" 'DOC Filter applied
On Error Resume Next
Set rngDocPl = ws.Range("AX2:AX1561").SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If rngDocPl Is Nothing Then MsgBox "No any visible cells in AX:AX column": Exit Sub
For Each cel In rngDocPl.cells
With wsDoc
Debug.Print "before, on row " & cel.row, cel.Offset(0, -43).value 'the cell in G:G before calculations
.Range("A3").value = cel.Offset(0, -43).value 'copy the value from G to "A3"
.Calculate
cel.Offset(0, -43).Resize(1, 19).value = .Range("D11:U11").value 'copy back the calculated range
Debug.Print "after, on row " & cel.row, cel.Offset(0, -43).value: Stop 'the cell in G:G after calculations
End With
Next
End Sub

Copying a row, inserting multiple new rows with the pasted info on multiple sheets Excel VBA

Data This is where all the items are with each region code
I have a "New Item" worksheet, a "Data" worksheet, and a "View" worksheet in the same workbook.
In my "New Item" worksheet, I have a section B2:H2 for inputing new items and click a button to run the macro. I need help fixing the error. It runs but adds a "true" to each point instead of the copied section.
I need the macro to add a line, copy the region code (in column A; there are over 30 regions but every item is added to a region by default), insert the B2:H2 in the B:H columns of the new line on the "Data" Sheet and also just add it to the end of the "View" sheet.
It keeps inputting true now. Why does it do this? Also, why does the code not copy the B2:H2? I am fairly new to VBA.
Also if possible, if there was a way to adjust the chart's Selected Data on the View sheet to add a line to the viewed data, that would be great. Ex: the chart shows 50 lines, and it adds another line to the selected data through the macro.
Thank you in advance for all suggestions. I can clarify anything or upload the excel if needed.
Here is the code so far:
Sub AddItem()
Sheets("Data").Select
Dim lastRow As Long
Dim rowPtr As Long
lastRow = Range("A" & Rows.Count).End(xlUp).Row
For rowPtr = lastRow To 2 Step -1
If Not IsEmpty(Range("A" & rowPtr)) Then
If Range("A" & rowPtr) <> Range("A" & rowPtr - 1) Then
Range("A" & rowPtr).EntireRow.Insert
End If
End If
Next
Sheets("New Item").Select
Application.ScreenUpdating = False
Dim copySheet As Worksheet
Dim pasteSheet1 As Worksheet
Set copySheet = Worksheets("New Item")
Set pasteSheet1 = Worksheets("Data")
copySheet.Range("B2:H2").Copy
pasteSheet1.Cells(Rows.Count, 1).End(xlUp).Offset(1, 1).PasteSpecial xlPasteValues
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
So im not sure if this is what you want.
Sub Add()
Dim Data As Worksheet, NItem As Worksheet, View As Worksheet
Dim lRow As Long
Application.ScreenUpdating = False
Set NItem = Worksheets("New Item")
Set Data = Worksheets("Data")
Set View = Worksheets("View")
lRow = View.Cells(View.Rows.Count, 2).End(xlUp).Row
Data.Range("A2").EntireRow.Insert
NItem.Range("B2:H2").Copy
Data.Range("B2").PasteSpecial xlPasteValues
View.Cells(lRow + 1, 2).PasteSpecial xlPasteValues
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
But this will add a line in Row 2 in the Datasheet, paste in the values. (Your For Loop inserts a new line after every entry, why?). It also pastes it in the viewsheet. Other than that please avoid using .Select and objectify .Range, .Cells etc. like you've done in the second part of the code.

Automatically creating worksheets based on a list in excel

I want to create a new sheet(Slave) with the name as entered in the cells A5:A50 in (master) sheet and copy the contents of the (template)sheet in the newly created slave sheet. I have got one program as below which closely matched with my requirement but 1) it doesnt take new values which i edit and create a new slave in the range provided i.e it is not dynamic and 2) i want to run the macro everytime i enter the value in the specified range.
Help would be highly appreciated
Sub CreateAndNameWorksheets()
Dim c As Range
Application.ScreenUpdating = False
For Each c In Sheets("Master").Range("A5:A50")
Sheets("Template").Copy After:=Sheets(Sheets.Count)
With c
ActiveSheet.Name = .Value
.Parent.Hyperlinks.Add Anchor:=c, Address:="", SubAddress:= _
"'" & .Text & "'!A1", TextToDisplay:=.Text
End With
Next c
Application.ScreenUpdating = True
End Sub
Put this code in the "Master" Sheet, every time you change a cell in the Range("A5:A50") it will run the desired code
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If (Target.Parent.Name = Range("A1:A50").Parent.Name) Then
Dim ints As Range
Set ints = Application.Intersect(Target, Range("A5:A50"))
If (Not (ints Is Nothing)) Then
'insert code here
End If
End If
End Sub

Force "F2"+"Enter" on range of cells

I have an Excel 2010 worksheet which has macros to copy data from other sheets into a specific format on another sheet.
The data copies but I have an issue with the formatting of cell ranges which hold date or time values.
The data originates from a database extract and everything is in text format. In my worksheet when I copy the date (via VBA) I apply the format "yyyy-mm-dd" for dates and "hh:mm.ss.ss" for times.
There is never a fixed amount of rows so I've set the VBA code to apply the formatting to the range of cells for example:
AssDateLastRow = shAss.Range("C" & Rows.Count).End(xlUp).Row
shAss.Range("C4:C" & AssDateLastRow).NumberFormat = "yyyy-mm-dd"
Not all cells in the range have the correct format, they will appear as 15/04/2014 not 2014-04-15. If I manually select the cell and press the F2 then ENTER keys the format appears as I need. This happens randomly through the range and there could be thousands of rows so it is not practical to trawl though the worksheet manually hitting F2+ENTER on each one.
I've looked on the internet and found what should automatically do the F2+ENTER with VBA.
The code below is extracted from a larger set of lines of code, so the Dim statements etc. are further up in the actual copy, but this should show the way I've tackled this so far.
Dim shAss As Worksheet
Dim AssDateLastRow As Long
Dim c As Range
'enter method to format 'Date Craftperson Assigned' and 'Time Craftperson Assigned' in Assignments sheet
'column "C" and "D", to formats required by Archibus: date "yyyy-mm-dd", time "hh:mm.ss.ss"
AssDateLastRow = shAss.Range("C" & Rows.Count).End(xlUp).Row
shAss.Range("C4:C" & AssDateLastRow).NumberFormat = "yyyy-mm-dd"
'ensure format is applied by forcing F2 edit of cell
For Each c In shAss.Range("C4:C" & AssDateLastRow).Cells
c.Select
SendKeys "{F2}", True
SendKeys "{ENTER}", True
'Selection.NumberFormat = "yyyy-mm-dd"
Next
When I run the code, the data copies into my worksheets but the dates and times are still in a mixed format.
The attempt at forcing the F2+ENTER via the VBA doesn't seemed to have done anything. If done manually it works okay.
Below is an example of data copied from the results in the worksheet
Work Request Code Date Assigned Time Assigned
92926 19/05/2014 14:30.00.00
92927 19/05/2014 15:00.00.00
92928 2014-05-19 15:15.00.00
92934 2014-05-19 14:00.00.00
92527 12/05/2014 07:30
92528 12/05/2014 08:00
92804 2014-05-12 16:15
92805 2014-05-12 16:20.00.00
I use this simple macro to apply F2 + Enter on the currently selected range:
Sub ApplyF2()
Selection.Value = Selection.FormulaR1C1
End Sub
I can think of two options to get Excel to apply the formatting to the cells in one step.
The first is to use the Text to columns functionality even though there is nothing in the column to split.
The second option is to copy a value of 1 and paste it into the cells using the Paste Special - Multiply option.
Although either method should force an update of the cell formating, I would lean towards the first option.
This is incase some of your dates are is stored as text.
Sub Format_Text_to_Columns()
Dim AssDateLastRow As Long
AssDateLastRow = ActiveSheet.Range("C" & Rows.Count).End(xlUp).Row
ActiveSheet.Range("C4:C" & AssDateLastRow).NumberFormat = "yyyy-mm-dd;#"
'Set the format
Range("C4:C" & AssDateLastRow).Select
Selection.TextToColumns DataType:=xlDelimited, ConsecutiveDelimiter:=True, _
Space:=True, FieldInfo:=Array(1, 5)
'Use text to columns to force a format update
End Sub
Sub Format_Paste_Special_Multiply()
Dim AssDateLastRow As Long
AssDateLastRow = ActiveSheet.Range("C" & Rows.Count).End(xlUp).Row
ActiveSheet.Range("C4:C" & AssDateLastRow).NumberFormat = "yyyy-mm-dd;#"
'Set the format
Range("C1").FormulaR1C1 = "1"
Range("C1").Copy
Range("C4:C" & AssDateLastRow).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlMultiply
Application.CutCopyMode = False
Range("C1").ClearContents
'Multiply the dates by 1 to force a format update
End Sub
I struggled to get this to work too. My problem has been not just dates but also data with a single quote in front of it. What I hacked together works great for me. It cleans up over 70,000 cells very fast. Hope it works for you:
(you will change the range and such to suit your needs)
Dim MyRange As Range
Set MyRange = Range(Cells(2, 7), [G1].End(xlDown))
For Each MyRange In MyRange.Cells
'Mimic F2 without SendKeys
MyRange.Value = MyRange.Value
Next
This worked for me.
Dim r As Range
Dim n As Integer
Dim AssDateLastRow As Long
AssDateLastRow = ActiveSheet.Range("E" & Rows.Count).End(xlUp).Row
Set r = Range("E2:E" & AssDateLastRow)
r.Select
r.NumberFormat = "ddmmyyyy;#"
r.Select
For n = 1 To r.Rows.Count
SendKeys "{F2}", True
SendKeys "{ENTER}", True
Next n
It is possible to use Text to Columns to solve this problem
1) Highlight the column of data
2) Go to Data -> Text To Columns -> Delimited -> (deselect everything) -> Next
3) On page 3 of the wizard, set the Column Data Format YMD
4) OK
Sub RefreshCells()
Dim r As Range, rr As Range
Set rr = Selection
For Each r In rr
r.Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
Application.SendKeys "{F2}"
Application.SendKeys "{ENTER}"
Application.SendKeys "+{ENTER}"
DoEvents
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
Application.SendKeys "{ENTER}"
DoEvents
Next
End Sub
It seems odd that you would need to send keys F2 + Enter. What is the formatting before you run the macro? Try formatting the whole column that way (it won't affect the text).
Columns("C:C").NumberFormat = "yyyy-mm-dd"
My variation
n = Selection.Rows.count
Dim r1 As range, rv As range
Set r1 = Selection.Cells(1, 1)
For I = 1 To n
Set rv = r1.offset(I - 1, 0)
vali = rv.value
IsNumeric(vali) Then
vali = CDbl(vali)
rv.value = 0
rv.value = vali
End If
Try to press F9 or File-Option-formulas-workbook calculation- automatic
I just set the cell to the right of the top entry equal to a formula that multiplied the problem cell times 1. That new cell was a proper number, so then double clicking the handle extended it down the whole column fixed them all!
Sendkeys are not stable. The better way is to store the text in the clipboard and paste it.
See here on how to store values in the clipboard
Sub CopyText(Text As String)
Dim MSForms_DataObject As Object
Set MSForms_DataObject = CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
MSForms_DataObject.SetText Text
MSForms_DataObject.PutInClipboard
Set MSForms_DataObject = Nothing
End Sub
Sub Test()
CopyText (ActiveCell.Value)
ActiveCell.PasteSpecial
End Sub
'In place of active cell, you may pass a range
This works for me
Sub f2Cells(sel as Range)
Dim rng as Range
On Error GoTo exitHere
With Application
.ScreenUpdating = False
.Calculation = xlCalculationManual
End With
For Each rng In sel.Cells
If Not Intersect(sel, Application.Range(rng.Address)) Is Nothing And _
Application.Range(rng.Address).EntireColumn.Hidden = False And _
Application.Range(rng.Address).EntireRow.Hidden = False Then
Application.Range(rng.Address).Application.SendKeys "({F2}{ENTER})", True
End If
Next rng
exitHere:
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
End With
Application.SendKeys "{NUMLOCK}", True
End Sub
Then from your function you can just call
f2Cells shAss.Range("C4:C" & AssDateLastRow)
I just got it, Simple
Select all the cells you want to hit F2 and Enter and run this short macro:
Sub AutoF2Enter()
Selection.Value = Selection.Value
End Sub
Works on date and numbers!
50.000 cells in a second!

Resources