I'm trying to combine an array of PDF into one with this code :
Option Explicit
Sub Fusion_PDFs(ByVal name As String, ByRef pdfs() As Variant)
Dim oPDDoc() As Object
Dim oPDDocFinal As Object
Dim Num As Long
Dim i As Integer
Set oPDDocFinal = CreateObject("AcroExch.PDDoc")
oPDDocFinal.Open (pdfs(0))
ReDim oPDDoc(UBound(pdfs))
For i = LBound(pdfs) + 1 To UBound(pdfs)
Set oPDDoc(i) = CreateObject("AcroExch.PDDoc")
oPDDoc(i).Open (pdfs(i))
Next i
For i = LBound(oPDDoc) To UBound(oPDDoc)
Num = oPDDocFinal.GetNumPages() - 1
oPDDocFinal.InsertPages Num, oPDDoc(i), 0, oPDDoc(i).GetNumPages(), True
Next i
oPDDocFinal.Save 1, ThisWorkbook.Path & "\DRT créés\" & name & ".pdf"
'Application.DisplayAlerts = False
For i = LBound(oPDDoc) To UBound(oPDDoc)
oPDDoc(i).Close
Set oPDDoc(i) = Nothing
Next i
oPDDocFinal.Close
Set oPDDocFinal = Nothing
'Application.DisplayAlerts = True
End Sub
I got a string array from another function which contains X path of pdfs. I already verified this array and there is nothing wrong with it, the problem is on this code. But i did a test version before rework it to works with my project, and the test version was working perfectly. The code is still very similar and i didn't change nothing on the creation and the fusion parts.
I first open an oPDDocFinal, which is the first pdf of my array "pdfs" (pdfs(0)) then i loop on the rest of the pdfs array to create a PDDoc array. Finally i loop on this PDDoc array to combine one by one all theses pdf with the oPDDocFinal.
But i got an error on this line :
oPDDocFinal.InsertPages Num, oPDDoc(i), 0, oPDDoc(i).GetNumPages(), True
i got the following error (i tried to translate from french) :
Execution error '91' :
Object variable or With bloc variable undefined
I didn't modified this part of code and it was working on my test script, but now i get this error. Do you know how can i solve my problem ?
Thanks for your attention.
Ok i found my error :
My first loop, i start at 1, so i take pdfs(1) to oPDDoc(1), but my first loop start at 0 so oPDDoc(0) doesn't exists.
I fixed it like that, and now it works :
Option Explicit
Sub Fusion_PDFs(ByVal name As String, ByRef pdfs() As Variant)
Dim oPDDoc() As Object
Dim oPDDocFinal As Object
Dim Num As Long
Dim i As Integer
Set oPDDocFinal = CreateObject("AcroExch.PDDoc")
oPDDocFinal.Open (pdfs(0))
ReDim oPDDoc(UBound(pdfs))
For i = LBound(pdfs) + 1 To UBound(pdfs)
Set oPDDoc(i - 1) = CreateObject("AcroExch.PDDoc")
oPDDoc(i - 1).Open (pdfs(i))
Next i
For i = LBound(oPDDoc) To UBound(oPDDoc) - 1
Num = oPDDocFinal.GetNumPages() - 1
oPDDocFinal.InsertPages Num, oPDDoc(i), 0, oPDDoc(i).GetNumPages(), True
Next i
oPDDocFinal.Save 1, ThisWorkbook.Path & "\DRT créés\" & name & ".pdf"
'Application.DisplayAlerts = False
'For i = LBound(oPDDoc) To UBound(oPDDoc) - 1
'
' oPDDoc(i).Close
' Set oPDDoc(i) = Nothing
'
'Next i
'
'oPDDocFinal.Close
'Set oPDDocFinal = Nothing
'Application.DisplayAlerts = True
End Sub
Thanks all for your attention !
Things to try:-
Does the environment that it is not working on have the same version of AcroExch and Word installed
Can both environments see the PDFs?
Is there contention of oPDDocFinal meaning something or someone else has it open (This thread implies it should be closed to update).
In debug, does oPDDoc(i) have a value
should it be bracketed - oPDDocFinal.InsertPages(Num, oPDDoc(i), 0, oPDDoc(i).GetNumPages(), True)
I also believe you may have an easier debugging in a single loop.
Dim oPDDoc As Object
Dim oPDDocFinal As Object
Dim Num As Long
Dim i As Integer
'Initialise objects
Set oPDDocFinal = CreateObject("AcroExch.PDDoc")
Set oPDDoc = CreateObject("AcroExch.PDDoc")
'Save a working copy
oPDDocFinal.Open (pdfs(0))
oPDDocFinal.Save 1, ThisWorkbook.Path & "\DRT créés\" & name & ".pdf"
oPDDocFinal.Close
'Reference the working copy
pdfs(0) = ThisWorkbook.Path & "\DRT créés\" & name & ".pdf"
'for all but the first item in the pdfs array
For i = LBound(pdfs) + 1 To UBound(pdfs)
'Open the working copy
oPDDocFinal.Open (pdfs(0))
'Open the additional PDF
oPDDoc.Open (pdfs(i))
'Get the page count of the working copy
Num = oPDDocFinal.GetNumPages() - 1
'Insert the additional PDF at the end of the working copy
oPDDocFinal.InsertPages Num, oPDDoc(i), 0, oPDDoc(i).GetNumPages(), True
'Close the additional PDF
oPDDoc.Close
'Save and close the working copy PDF
oPDDocFinal.Save
oPDDocFinal.Close
Next i
'Release objects
Set oPDDocFinal = Nothing
Set oPDDoc = Nothing
This would be a heavyweight loop but should act as a starting point to debugging. I should also add I do not have AcroExch. The above is theoretical.
Related
The code below works in excel for windows, but not in excel for mac.
It gives error 9 subscript out of range.
When I run the code in my Windows machine, everything is fine.
When I try to run it in a Mac with excel for Mac then I get the error message in the procedure below and the line added at the end of this post.
Sub GetUniqueID(aFirstArray() As Variant, DataUniqueID As Variant)
Dim aUniqueArray() As Variant
Dim lngCountFirst As Long
Dim lngCountUnique As Long
Dim bolFoundIt As Boolean
Dim strOne As String
Dim strTwo As String
Dim i As Integer
Dim j As Integer
Dim ColIndex As Integer
ColIndex = 1
'// Redim with one element, empty at this point.//
ReDim aUniqueArray(0)
'// loop thru ea element in our first array. (This is our outer loop)//
For lngCountFirst = LBound(aFirstArray()) To UBound(aFirstArray())
'// ensure that we flag as False at the start of ea loop//
bolFoundIt = False
'// In a secondary, inner loop, we can build the unique array, only //
'// adding items that have not already been added. //
For lngCountUnique = LBound(aUniqueArray()) To UBound(aUniqueArray())
'// For ea element in our unique array, see if it matches the //
'// current element being looked at in our frist array. If we //
'// find a match, mark our flag/boolean and exit the inner loop.//
'// On the other hand, if no match is found after every element //
'// in our unique array is looked at, then bolFoundIt will still//
'// be False. //
If aUniqueArray(lngCountUnique) = aFirstArray(lngCountFirst, ColIndex) Then
bolFoundIt = True
Exit For
End If
Next lngCountUnique
'// Now if bolFound is still False, then we didn't find a match, so //
'// we'll add it to the last available element in our unique array //
'// and add another empty element to the unique array for the next //
'// round... Note the use of Redim Preserve, so that we don't //
'// lose the values already added. //
If Not bolFoundIt Then
aUniqueArray(UBound(aUniqueArray())) = aFirstArray(lngCountFirst, ColIndex)
ReDim Preserve aUniqueArray(UBound(aUniqueArray()) + 1)
End If
Next lngCountFirst
'// Now after we're all done, we left our unique array with one //
'// extra/unused element. We'll drop/kill the extra element here. //
ReDim Preserve aUniqueArray(UBound(aUniqueArray()) - 1)
ReDim DataUniqueID(1 To UBound(aUniqueArray()) + 1, 1 To UBound(aFirstArray, 2))
For i = 1 To UBound(DataUniqueID)
DataUniqueID(i, 1) = aUniqueArray(i - 1)
Next i
For i = 1 To UBound(DataUniqueID)
For j = 2 To UBound(aFirstArray)
If DataUniqueID(i, 1) = aFirstArray(j, 1) Then
DataUniqueID(i, 5) = DataUniqueID(i, 5) & "," & aFirstArray(j, 5)
DataUniqueID(i, 7) = DataUniqueID(i, 7) & "," & aFirstArray(j, 7)
DataUniqueID(i, 12) = DataUniqueID(i, 12) & "," & aFirstArray(j, 12)
DataUniqueID(i, 14) = DataUniqueID(i, 14) & "," & aFirstArray(j, 14)
End If
Next j
Next i
End Sub
The line with error is this one:
ReDim Preserve aUniqueArray(UBound(aUniqueArray()) - 1)
Any ideas?
--Edit2---
this sub is called from another sub:
Dim Data() As Variant
'more code between
'but nothing that changes the dimensions of Data. Just assigning values loops etc
'***** Create an array with the Data for faster operation
Data = ThisWorkbook.Worksheets("CDR").Range("A1:V" & LastRow).Value
'more code here
'Test the conditional compiler constant #Mac
#If Mac Then
'I am a Mac
'Define Folder Path
'Function to create folder if it not exists in the Microsoft Office Folder
'Ron de Bruin : 13-July-2020
Dim OfficeFolder As String
Dim TestStr As String
OfficeFolder = MacScript("return POSIX path of (path to desktop folder) as string")
OfficeFolder = Replace(OfficeFolder, "/Desktop", "") & "Library/Group Containers/UBF8T346G9.Office/Script #1 output - " & FilenameDateStamp
On Error Resume Next
TestStr = Dir(OfficeFolder & "*", vbDirectory)
On Error GoTo 0
If TestStr = vbNullString Then
MkDir OfficeFolder
'You can use this msgbox line for testing if you want
'MsgBox "You find the new folder in this location :" & PathToFolder
End If
'14. SAVE OUTPUT FILES part 2 - save first set of output files
' File #1 & 2 --Save the current spreadsheet in it's entirety, as a new Excel and CSV version named dynamically as
'"For import - Mojo CallDetailParsed_yyyy-mm-dd_hh-mm.xlsx"
'(and a copy in .csv format)
' copies a worksheet into a new file and saves it onto desktop
Dim newWB As Workbook
ThisWorkbook.Sheets("CDR").Select
Set newWB = Workbooks.Add
ThisWorkbook.Sheets("CDR").Copy Before:=newWB.Sheets(1)
'this saves the new workbook
With newWB
'.SaveAs FileName:="[FONT=arial][COLOR=black]Macintosh HD:Users:robertandres[/COLOR][/FONT]:Desktop:TEST.xlsx", FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
.SaveAs FileName:=OfficeFolder & "/For import - Mojo CallDetailParsed_" & FilenameDateStamp, FileFormat:=51
.Saved = True
.SaveAs FileName:=OfficeFolder & "/For import - Mojo CallDetailParsed_" & FilenameDateStamp, FileFormat:=22
.Close
End With
'15. SAVE OUTPUT FILES part 2 - save second set of output files
'File #2 & 3 which is the same as the above but contains only columns A, F, L, V
'"For import - Mojo phone tags from calldetail Parsed_yyyy-mm-dd_hh-mm.xslx"
'(and a copy in .csv format)
' copies a worksheet into a new file and saves it onto desktop
Dim newWB2 As Workbook
ThisWorkbook.Sheets("CDR").Select
Set newWB2 = Workbooks.Add
ThisWorkbook.Sheets("CDR").Copy Before:=newWB2.Sheets(1)
newWB2.Sheets("CDR").Columns("M:U").Delete
newWB2.Sheets("CDR").Columns("G:K").Delete
newWB2.Sheets("CDR").Columns("B:E").Delete
'this saves the new workbook
With newWB2
'.SaveAs FileName:="[FONT=arial][COLOR=black]Macintosh HD:Users:robertandres[/COLOR][/FONT]:Desktop:TEST.xlsx", FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
.SaveAs FileName:=OfficeFolder & "/For import - Mojo phone tags from calldetail Parsed" & FilenameDateStamp, FileFormat:=51
.Saved = True
.SaveAs FileName:=OfficeFolder & "/For import - Mojo phone tags from calldetail Parsed" & FilenameDateStamp, FileFormat:=22
.Close
End With
#Else
'I am Windows
'code for windows that works ok
#End If
'prevent flickering and make faster
Application.ScreenUpdating = True
Dim DataUniqueID() As Variant
Call GetUniqueID(Data, DataUniqueID)
I created the macro for windows, and then it had to work also in Mac.
I did not have access to mac so in mind everything was tested but only in windows, not in mac.
The problem was that above the code in the question, I was importing data. The code to import data was not working for mac. When I fixed that code, everything worked fine.
Assumptions and poor testing was the problem. I solved this when I got full access to a mac.
Thanks #faneduru
I have the next code:
Function findRanges(keyword) As Variant()
Dim foundRanges(), rngSearch As Range
Dim i, foundCount As Integer
i = 0
foundCount = 0
ReDim foundRanges(0)
Set rngSearch = ActiveDocument.Range
Do While rngSearch.Find.Execute(FindText:=keyword, MatchWholeWord:=True, Forward:=True) = True
Set foundRanges(i) = rngSearch.Duplicate
i = i + 1
ReDim Preserve foundRanges(UBound(foundRanges) + 1)
rngSearch.Collapse Direction:=wdCollapseEnd
Loop
ReDim Preserve foundRanges(UBound(foundRanges) - 1)
findRanges = foundRanges
End Function
And:
Sub test()
Dim rngIAM_Code() As Range
...
Dim rngIAM_Title() As Range
rngIAM_Code = findRanges("IAM_Code")
...
rngIAM_Title = findRanges("IAM_Title")
End Sub
What is very confuding is that sometimes the compiler says "Can't assign to array" and sometimes it works fine. For example, when I only try to search one value and populate one array, the code works. When I try to populate both array, there is an error "Can't assign to an array". I can then switch lines of code like this:
rngIAM_Title = findRanges("IAM_Title")
...
rngIAM_Code = findRanges("IAM_Code")
And then the error happens with another array. The error can happen anywhere: on the first line, in the middle, or in the end, but it is consistent as long as I don't move lines. And again, if I leave only one-two lines of code with arrays in sub "test"everything works fine.
The following works for me.
In this code, every object variable is explicitly assigned a type. In VBA, every variable must be typed, else it's assigned the type Variant by default. In the following declaration line, for example, foundRanges() is of type Variant because it's not followed by As with a data type. The same with i in the next line of code in the question.
Dim foundRanges(), rngSearch As Range
And since the arrays in the calling procedure are of type Range the function should return the same type.
I also took the liberty of passing the Document object to the function as, conceivably, some day the document in question might not be ActiveDocument but a Document object assigned using Documents.Open or Documents.Add. If this is not desired it can be changed back, but not relying on ActiveDocument is more reliable...
Additionally, I added the Wrap parameter to Find.Execute - it's always a good idea to specify that when executing Find in a loop to prevent the search from starting again at the beginning of the document (wdFindContinue).
Sub testRangesInArrays()
Dim rngIAM_Code() As Range
Dim rngIAM_Title() As Range
rngIAM_Code = findRanges("You", ActiveDocument)
rngIAM_Title = findRanges("change", ActiveDocument)
End Sub
Function findRanges(keyword As String, doc As Word.Document) As Range()
Dim foundRanges() As Range, rngSearch As Range
Dim i As Integer, foundCount As Integer
i = 0
foundCount = 0
ReDim foundRanges(0)
Set rngSearch = doc.content
Do While rngSearch.Find.Execute(findText:=keyword, MatchWholeWord:=True, _
Forward:=True, wrap:=wdFindStop) = True
Set foundRanges(i) = rngSearch.Duplicate
ReDim Preserve foundRanges(UBound(foundRanges) + 1)
i = i + 1
rngSearch.Collapse Direction:=wdCollapseEnd
Loop
findRanges = foundRanges
End Function
Here is an alternative based on a Collection instead of an Array:
I used also included Cindys Input regarding passing the document and adding wrap.
I don't exactly know what the you use the return value for, but in general a collection is a bit more flexible than an Array.
I also removed the underscores since they indicate a function of an implemented Interface and may cause problems later down the line. are used when implementing an Interface (improves readability).
As explained here you can use wrap or collapse to prevent a continuous Loop.
Option Explicit
Sub test()
Dim rngIAMCode As Collection
Dim rngIAMTitle As Collection
Set rngIAMCode = findRanges("IAM_Code", ActiveDocument)
Set rngIAMTitle = findRanges("IAM_Title", ActiveDocument)
Debug.Print "Code found : " & rngIAMCode.Count & " Times."
Debug.Print "Title found : " & rngIAMTitle.Count & " Times."
End Sub
Function findRanges(ByVal keyword As String, doc As Document) As Collection
Set findRanges = New Collection
Dim rngSearch As Range
Set rngSearch = doc.Content
With rngSearch.Find
.Text = keyword
.MatchWholeWord = True
.Forward = True
.Wrap = wdFindStop
While .Execute
findRanges.Add rngSearch.Duplicate
rngSearch.Collapse Direction:=wdCollapseEnd
Wend
End With
End Function
Scenario: I have a workbook with multiple worksheets. I am trying to use a function (called within a sub) to export arrays with data from certain worksheets. The arrays are created before the function with the content from the worksheet with:
If ws.Name = "AA" Then
expaa = ws.UsedRange.Value
End if
where expaa is previously defined as variant.
The function I am using apparently finishes running, but the output on the new file saved is weird: instead of having one row of headers, the first row is split into 2 for some reason (all the others remain the same).
This is the function I am using:
Function Exporter(arr As Variant, y As String, OutPath As String) As Variant
Dim lrow As Long, lColumn As Long
Dim w2 As Workbook
Dim d As Date
Workbooks.Add
Set w2 = ActiveWorkbook
w2.Worksheets(1).Range("A1").Resize(UBound(arr, 1), UBound(arr, 2)) = arr
Application.DisplayAlerts = False
w2.SaveAs Filename:=OutPath & "\" & y, FileFormat:=6
Application.DisplayAlerts = True
w2.Close True
End Function
Which I call from the main sub with:
If aa_name <> "" Then
Exporter expaa , "aa_OK", wbpath
End If
where aa_name is the name of the file used to retrieve the path.
Obs: The wbpath variable is a string with the path of my main workbook (therefore the new file is saved at the same location).
Question: What may be causing the first row of my output to be split? How can that be fixed?
Obs2: I know this can be done with copy procedure, and looping through the array and so on. I even got it to work with other methods. This post is only to understand what I am doing wrong with the current code.
Obs3: Regarding the data that is going to be passed: it is a matrix of days, identifiers and data, ex:
Item1 Item2 Item3
01/01/2000 1 1 2
02/01/2000 1 2 1
03/01/2000 2 2 2
with around 2000 rows and 3000 columns.
UPDATE: After retesting the code multiple times, It appears that the data of the first row only gets split when the file is save as csv (when the array is pasted, the output is normal). Any idea on what may be the cause for that?
I know this is old but here is my solution for the googlers. This accepts an array and creates a CSV at a path you define. Its probably not perfect but it has worked so far for me.
Option Explicit
Option Private Module
Public Function SaveTextToFile(ByVal targetarray As Variant, ByVal filepath As String) As Boolean
On Error GoTo CouldNotMakeFile
Dim fso As FileSystemObject
Set fso = New FileSystemObject
Dim fileStream As TextStream
' Here the actual file is created and opened for write access
Set fileStream = fso.CreateTextFile(filepath)
' Write something to the file
Dim Row As Long, Col As Long
For Row = LBound(targetarray, 1) To UBound(targetarray, 1)
For Col = LBound(targetarray, 2) To UBound(targetarray, 2)
fileStream.Write StringCompliance(targetarray(Row, Col)) & IIf(Col = UBound(targetarray, 2), "", ",")
Next Col
fileStream.WriteBlankLines 1
Next Row
' Close it, so it is not locked anymore
fileStream.Close
' Here is another great method of the FileSystemObject that checks if a file exists
If fso.FileExists(filepath) Then
SaveTextToFile = True
End If
CouldNotMakeFile:
End Function
Private Function StringCompliance(ByVal InputString As String) As String
Dim CurrentString As String
CurrentString = InputString
'Test if string has qoutes
If InStr(CurrentString, Chr$(34)) > 0 Then
CurrentString = Chr$(34) & Replace(CurrentString, Chr$(34), Chr$(34) & Chr$(34)) & Chr$(34)
StringCompliance = True
Else
'Tets if string has commas or line breaks
If InStr(CurrentString, ",") > 0 Or InStr(CurrentString, vbLf) > 0 Then
CurrentString = Chr$(34) & CurrentString & Chr$(34)
Else
StringCompliance = False
End If
End If
StringCompliance = CurrentString
End Function
I try to open all *.xlsx files in a specified folder and store the filehandles in an array.
My code looks like this
Dim Files() As Workbook
ReDim Files(Count)
File = Dir(Path & "\*.xlsx")
Count = 0
Do While File <> ""
Set Files(Count) = Workbooks.Open(Path & File, , True)
Count = Count + 1
File = Dir()
Loop
The code seems to work, however, when I run it a second time (hitting the run button again), I get an error number 13.
Debugging the code I tracked the problem to the line
Set Files(Count) = Workbooks.Open(Path & File, , True)
As I am unexperienced with vba I guess I didn't do this the right way...
What would be a preferable way to store filehandles to all files in a specific folder in an array?
you're missing a path separator
Set Files(Count) = Workbooks.Open(Path & "\" & File, , True)
The code should be:
Dim Files() As Workbook
Dim Count As Integer
ReDim Files(Count)
File = Dir(Path & "\*.xlsx")
Count = 0
Do While File <> ""
ReDim Preserve Files(Count)
Set Files(Count) = Workbooks.Open(Path & File, , True)
Count = Count + 1
File = Dir()
Loop
You need to redim your array. Preserve keeps the existing data.
I have written a VB.NET application in Visual Studio 2015. (first time ever had any contact with visual basic or VS). The application takes an input csv file, analyses it and splits it according to that analysis into 2 output csv files. For one of these output files, I then need to change every blank cell to have the value of zero. My prob, is that the code i've made is processing 750 input csv files to produce 1500 output files and each process in the loop is taking 5 mins meaning it's taking up to 5 days to run!! That is too long!
I'm trying to work out how to make the code run quicker. One easy first step would be in the blank cell to zero operation as i'm currently doing it cell by cell. I read that better to do via an array but i'm unsure how to code it...Can someone help?
My code now is:
Dim forceDataRangeDest, cell As Excel.Range
Dim blank As String
Dim forceDataRow, lastDataRow As Integer
'copy force data from original workbook to sheet 1 of new workbook
If ws.Range("Z" & (forceLegRowStart + 1)).Value = "Force Plate 3" Then
forceDataRow = forceDataRow + 2
forceDataRangeSrc = ws.Range("Z" & forceDataRow & ":AK" & lastDataRow)
Else forceDataRangeSrc = ws.Range("A" & forceDataRow & ":M" & lastDataRow)
End If
wsData = wbForce.Sheets("Sheet1")
wsData.Name = "Data"
forceDataRangeDest = wsData.Range("A1")
forceDataRangeSrc.Copy(forceDataRangeDest)
'insert new column A if Force Plate 3 data is one taken for the time interval data of column A
If ws.Range("Z" & (forceLegRowStart + 1)).Value = "Force Plate 3" Then
wsData.Columns("A:A").Insert(1)
'write in the Data
forceDataRangeSrc = ws.Range("A" & forceDataRow & ":A" & lastDataRow)
forceDataRangeSrc.Copy(wsData.Range("A1"))
End If
forceDataRangeDest = wsData.Range("A1:M" & ((lastDataRow - forceDataRow) + 1))
For Each cell In forceDataRangeDest
blank = cell.Value
If String.IsNullOrWhiteSpace(blank) Then
cell.Value = 0
End If
Next
It is the For Each cell at the bottom of this sample code that i think is really increasing the process time...how would i write that as an array and then write array into excel in one go?
Many thanks for any help you can give.
You could use the Range.Find and Range.FindNext methods in VBA which would be quicker than looping through all the cells. Here's an example of the VBA code:
Sub FindEmptyCells()
Dim found As Range
Dim firstCell As String
Set found = ActiveSheet.UsedRange.Find(What:="", LookAt:=xlWhole)
firstCell = found.Address
Do While Not (found Is Nothing)
Debug.Print found.Address
Set found = ActiveSheet.UsedRange.FindNext(found)
If found.Address = firstCell Then
Exit Do
End If
Loop
End Sub
EDIT: Added the code to use OP's range object
Dim found As Range
Dim firstCell As String
Set found = forceDataRangeDest.Find(What:="", LookAt:=xlWhole)
firstCell = found.Address
Do While Not (found Is Nothing)
found.Value = 0
Set found = forceDataRangeDest.FindNext(found)
If found.Address = firstCell Then
Exit Do
End If
Loop