Upload files creating dynamic folder based on the user input in asp - asp-classic

Here is my code that uploads a file to a folder...but I need to upload a file to a folder which might not exist yet. How can i create a folder before uploading the file or is there a parameter in asp that creates a folder before copying the file there if it doesn't exit?..i need to create folder based on the user input...
<%
Class FileUploader
Public Files
Private mcolFormElem
Private Sub Class_Initialize()
Set Files = Server.CreateObject("Scripting.Dictionary")
Set mcolFormElem = Server.CreateObject("Scripting.Dictionary")
End Sub
Private Sub Class_Terminate()
If IsObject(Files) Then
Files.RemoveAll()
Set Files = Nothing
End If
If IsObject(mcolFormElem) Then
mcolFormElem.RemoveAll()
Set mcolFormElem = Nothing
End If
End Sub
Public Property Get Form(sIndex)
Form = ""
If mcolFormElem.Exists(LCase(sIndex)) Then Form = mcolFormElem.Item(LCase(sIndex))
End Property
Public Default Sub Upload()
Dim biData, sInputName
Dim nPosBegin, nPosEnd, nPos, vDataBounds, nDataBoundPos
Dim nPosFile, nPosBound
biData = Request.BinaryRead(Request.TotalBytes)
nPosBegin = 1
nPosEnd = InstrB(nPosBegin, biData, CByteString(Chr(13)))
If (nPosEnd-nPosBegin) <= 0 Then Exit Sub
vDataBounds = MidB(biData, nPosBegin, nPosEnd-nPosBegin)
nDataBoundPos = InstrB(1, biData, vDataBounds)
Do Until nDataBoundPos = InstrB(biData, vDataBounds & CByteString("--"))
nPos = InstrB(nDataBoundPos, biData, CByteString("Content-Disposition"))
nPos = InstrB(nPos, biData, CByteString("name="))
nPosBegin = nPos + 6
nPosEnd = InstrB(nPosBegin, biData, CByteString(Chr(34)))
sInputName = CWideString(MidB(biData, nPosBegin, nPosEnd-nPosBegin))
nPosFile = InstrB(nDataBoundPos, biData, CByteString("filename="))
nPosBound = InstrB(nPosEnd, biData, vDataBounds)
If nPosFile <> 0 And nPosFile < nPosBound Then
Dim oUploadFile, sFileName
Set oUploadFile = New UploadedFile
nPosBegin = nPosFile + 10
nPosEnd = InstrB(nPosBegin, biData, CByteString(Chr(34)))
sFileName = CWideString(MidB(biData, nPosBegin, nPosEnd-nPosBegin))
oUploadFile.FileName = Right(sFileName, Len(sFileName)-InStrRev(sFileName, "\"))
nPos = InstrB(nPosEnd, biData, CByteString("Content-Type:"))
nPosBegin = nPos + 14
nPosEnd = InstrB(nPosBegin, biData, CByteString(Chr(13)))
oUploadFile.ContentType = CWideString(MidB(biData, nPosBegin, nPosEnd-nPosBegin))
nPosBegin = nPosEnd+4
nPosEnd = InstrB(nPosBegin, biData, vDataBounds) - 2
oUploadFile.FileData = MidB(biData, nPosBegin, nPosEnd-nPosBegin)
If oUploadFile.FileSize > 0 Then Files.Add LCase(sInputName), oUploadFile
Else
nPos = InstrB(nPos, biData, CByteString(Chr(13)))
nPosBegin = nPos + 4
nPosEnd = InstrB(nPosBegin, biData, vDataBounds) - 2
If Not mcolFormElem.Exists(LCase(sInputName)) Then mcolFormElem.Add LCase(sInputName), CWideString(MidB(biData, nPosBegin, nPosEnd-nPosBegin))
End If
nDataBoundPos = InstrB(nDataBoundPos + LenB(vDataBounds), biData, vDataBounds)
Loop
End Sub
'String to byte string conversion
Private Function CByteString(sString)
Dim nIndex
For nIndex = 1 to Len(sString)
CByteString = CByteString & ChrB(AscB(Mid(sString,nIndex,1)))
Next
End Function
'Byte string to string conversion
Private Function CWideString(bsString)
Dim nIndex
CWideString =""
For nIndex = 1 to LenB(bsString)
CWideString = CWideString & Chr(AscB(MidB(bsString,nIndex,1)))
Next
End Function
End Class
Class UploadedFile
Public ContentType
Public FileName
Public FileData
Public Property Get FileSize()
FileSize = LenB(FileData)
End Property
Public Sub SaveToDisk(sPath)
Dim oFS, oFile
Dim nIndex
If sPath = "" Or FileName = "" Then Exit Sub
If Mid(sPath, Len(sPath)) <> "\" Then sPath = sPath & "\"
Set oFS = Server.CreateObject("Scripting.FileSystemObject")
If Not oFS.FolderExists(sPath) Then Exit Sub
Set oFile = oFS.CreateTextFile(sPath & FileName, True)
For nIndex = 1 to LenB(FileData)
oFile.Write Chr(AscB(MidB(FileData,nIndex,1)))
Next
oFile.Close
End Sub
Public Sub SaveToDatabase(ByRef oField)
If LenB(FileData) = 0 Then Exit Sub
If IsObject(oField) Then
oField.AppendChunk FileData
End If
End Sub
End Class
%>
can anybody help me?
i need to upload the set of documents corresponding to that proforma number...so i need to create a folder in the name of proforma number which is entered by the user...

just use the filesystemobject to create a directory like so:
dim fso : set fso = server.createobject("scripting.filesystemobject")
dim absolutePath : absolutePath = "d:\path\to\new\directory"
if not fso.FolderExists(absolutePath) then
fso.createFolder( absolutePath )
end if
set fso = nothing
check the api doc for fso
to use that "proforma" number just get it from request.form("name_for_proforma_field")...
as you are using the upload class you have to use
fileUploader.Form("name_for_proforma_field")
instead of
request.form
because after using request.binaryread you do not have access to the request.forms collection...
brief example (not tested):
dim upl : set upl = new FileUploader()
upl.upload()
' from now on you have to use upl.Form() instad of request.form
dim folderName : folderName = upl.Form("name_for_proforma_field")
dim fso : set fso = server.createobject("scripting.filesystemobject")
dim absolutePath : absolutePath = "d:\path\to\new\directory\" & folderName
if not fso.FolderExists(absolutePath) then
fso.createFolder( absolutePath )
end if
set fso = nothing
for further information about the fileupload class have a look here

Related

How can I stop Ionic zip from appending null to the end of a file

I have a VB.net (ASPX) which receives a file (data stream) from my application, and depending on switches will save the file as is or compress & encrypt it using ionic.zip. When a file is saved without encryption it is byte perfect. When the same file is compressed/encrypted and then decrypted/uncompressed there is an extra null (ascii(0)) character appended to the end of the decrypted file. This is generally not an issue, but MS Office products complain about corrupted files (then opens them fine).
The code I use is fairly straightforward and I cannot see any issues. I found nothing in my searches for this issue with ionic zip. Here is the code;
<%# Page Language="VB" validateRequest="false"%>
<%# Import Namespace="Ionic.Zip"%>
<%# Import Namespace="System.Web.HttpContext"%>
<script Runat="Server">
Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
Dim strToken As String = Request.QueryString("token")
Dim strSessionID As String = Request.QueryString("SessionID")
Dim strAlternateFileName As String = Request.QueryString("AlternateFileName")
Dim strDestinationFolder As String = Request.QueryString("DestinationFolder")
Dim strZipYN As String = Request.QueryString("ZipYN")
Dim strZipFileName As String = Request.QueryString("ZipFileName")
Dim strZipPassword As String = Request.QueryString("ZipPassword")
Dim fileName As String = System.IO.Path.GetFileName(Request.Files(0).FileName)
If IsNothing(Current.Session("token" & strSessionID)) _
Then
Current.Session("token") = strToken
Current.Session("token" & strSessionID) = Current.Session("token")
End If
If Len(strAlternateFileName) > 0 _
Then
fileName = strAlternateFileName
End If
If strZipYN <> "Y" _
Then
Request.Files(0).SaveAs(Server.MapPath(strDestinationFolder + "/") + fileName)
Else
Dim fileIn As HttpPostedFile
Dim objZipFile As ZipFile = New ZipFile
fileIn = Request.Files(0)
Dim intFileInLen = fileIn.ContentLength
Dim bytFielIn(intFileInLen) As Byte
Dim strmFileIn As System.IO.Stream
strmFileIn = fileIn.InputStream
strmFileIn.Read(bytFielIn, 0, intFileInLen)
If strZipPassword.Length > 0 _
Then
objZipFile.Password = strZipPassword
objZipFile.Encryption = EncryptionAlgorithm.WinZipAes256
End If
objZipFile.AddEntry(fileName, bytFielIn)
objZipFile.SaveSelfExtractor(Server.MapPath(strDestinationFolder + "/") + strZipFileName + ".exe", SelfExtractorFlavor.WinFormsApplication)
' objZipFile.SaveSelfExtractor(Server.MapPath(strDestinationFolder + "/") + strZipFileName + ".zip", SelfExtractorFlavor.WinFormsApplication)
objZipFile.Dispose()
objZipFile = Nothing
'Create a PW protected ZIP only for non windows computers.
objZipFile = New ZipFile
If strZipPassword.Length > 0 _
Then
objZipFile.Password = strZipPassword
objZipFile.Encryption = EncryptionAlgorithm.WinZipAes256
End If
objZipFile.AddEntry(fileName, bytFielIn)
objZipFile.Save(Server.MapPath(strDestinationFolder + "/") + strZipFileName + ".zip")
objZipFile.Dispose()
objZipFile = Nothing
End If
End Sub
</script>
Any ideas?
Edit:
I get the same results whether I extract the file from the ".exe" file, or the ".zip" file

Initiating an Dynamic Multidimensional Array in VB.net

I am receiving a "Object reference not set to an instance of an object." Error when trying to populate the fileDetails array. I am new to vb.net and I am lost.
Public Sub FindAllOrphanFiles(ByVal targetDirectory As String)
Dim fileEntries As String() = Directory.GetFiles(targetDirectory)
' Process the list of files found in the directory.
Dim files As String
Dim iCount As Integer = 0
Dim fileDetails As String(,)
For Each files In fileEntries
Dim fileIcon As String
Dim thisFile As New IO.FileInfo(files)
Dim fileName As String = thisFile.Name
Dim fileSize As String = thisFile.Length
Dim fileDateModified As String = thisFile.LastWriteTime
Dim fileExtension As String = Path.GetExtension(fileName)
Dim fileShortPath As String = Replace(Replace(files, uploadFolderPath, ""), fileName, "")
Dim fileFullPath As String = files
If fileExtension = ".pdf" Then
fileIcon = "acrobat"
Else
fileIcon = "paint"
End If
' Write to Array
fileDetails(iCount, 0) = fileIcon
fileDetails(iCount, 1) = fileName
fileDetails(iCount, 2) = fileShortPath
fileDetails(iCount, 3) = fileDateModified
fileDetails(iCount, 4) = fileSize
fileDetails(iCount, 5) = fileFullPath
iCount += 1
Next files
Dim subdirectoryEntries As String() = Directory.GetDirectories(targetDirectory)
' Recurse into subdirectories of this directory.
Dim subdirectory As String
For Each subdirectory In subdirectoryEntries
FindAllOrphanFiles(subdirectory)
Next subdirectory
End Sub 'FindAllOrphanFiles
Any help would be greatly appreciated.
Your array is not initialized. If you know the size at some point before your loop, you should initialize it using REDIM:
Dim fileDetails As String(,)
redim fileDetails(fileEntries.Count -1,5)
For Each files In fileEntries
....
If you don't know it ahead of time, use Redim Preserve inside you loop:
Dim fileDetails As String(,)
Dim I as int32 = -1
For Each files In fileEntries
I += 1
redim preserve fileDetails(i,5)
....

convert existing code to asynchronous workings

I have existing code in VB in which I need to process all records that are in the list in one go, and await for their responses. When they respond, add them to the data table. The code works. I just need to convert it to run asynchronously.
Here is my code:
Imports System.Net
Imports System.IO
Public Class Form1
Dim _Datatable As New DataTable
Private Sub btnProcess_Click(sender As System.Object, e As System.EventArgs) Handles btnProcess.Click
prgProgress.Value = 0
prgProgress.Maximum = lstUrls.Items.Count
For Each _ProductEntry As String In lstUrls.Items
Try
Dim _Webclient As New WebClient
'_Webclient.Proxy = _ProxyClient
Dim _DataStream As Stream = _Webclient.OpenRead(New Uri(_ProductEntry))
Dim _DataRead As New StreamReader(_DataStream)
Dim _HtmlContent As String = _DataRead.ReadToEnd
Dim _HtmlDocument As mshtml.IHTMLDocument2 = New mshtml.HTMLDocument
_HtmlDocument.write(_HtmlContent)
Dim _ProductName As mshtml.IHTMLHeaderElement = _HtmlDocument.getElementById("product-header")
_DataStream.Close()
_DataRead.Close()
Call CheckTable("Name")
Call CheckTable("URL")
Call CheckTable("Image")
Call CheckTable("Price")
Dim _Price As String = String.Empty
Dim _SpanElements As mshtml.IHTMLElementCollection = _HtmlDocument.getElementsByTagName("span")
For Each _SpanElement As mshtml.IHTMLSpanElement In _SpanElements
If _SpanElement.classname = "regular-price" Then
_Price = Replace(Replace(_SpanElement.innertext, "£", ""), "Incl. VAT", "")
End If
Next
Dim _ImageLocation As String = String.Empty
For Each _Paragraph As mshtml.IHTMLElement In _HtmlDocument.getElementsByTagName("image")
If _Paragraph.id = "product-image-main" Then
Dim _Image As mshtml.IHTMLImgElement = CType(_Paragraph, mshtml.IHTMLImgElement)
_ImageLocation = _Image.src
Exit For
End If
Next
Dim tableElements As mshtml.IHTMLElementCollection
tableElements = _HtmlDocument.getElementsByTagName("Table")
Dim oTableTest As mshtml.IHTMLTable2 = tableElements.item(1)
'BUILD HEADERS
For Each _ColumnHeader As mshtml.IHTMLTableRow In oTableTest.rows
CheckTable(CType(_ColumnHeader.cells(0), mshtml.IHTMLElement).innerText)
Next
Dim _DataRow As DataRow = _DataTable.NewRow
_DataRow.Item("Name") = CType(_ProductName, mshtml.IHTMLElement).innerText
_DataRow.Item("URL") = _ProductEntry
_DataRow.Item("Price") = _Price
_DataRow.Item("Image") = _ImageLocation
For Each _RowData As mshtml.IHTMLTableRow In oTableTest.rows
Dim _Header As mshtml.IHTMLElement = _RowData.cells(0)
Dim _Value As mshtml.IHTMLElement = _RowData.cells(1)
_DataRow.Item(_Header.innerText) = _Value.innerText
Next
Dim _Elements As mshtml.IHTMLElementCollection = _HtmlDocument.all
For Each _Element As mshtml.IHTMLElement In _Elements
If _Element.className = "product-description product-documents" Then
For Each _ProductLink As mshtml.IHTMLElement In _Element.all
If _ProductLink.tagName = "A" Then
CheckTable(_ProductLink.innerText)
_DataRow(_ProductLink.innerText) = Replace(CType(_ProductLink, mshtml.IHTMLAnchorElement).href, "about:", "http://www.tapoutlet.co.uk")
End If
Next
End If
Next
_DataTable.Rows.Add(_DataRow)
_DataTable.AcceptChanges()
dgvScrapedData.DataSource = _Datatable
dgvScrapedData.Refresh()
Catch ex As Exception
Console.WriteLine("Error getting webpage-" & _ProductEntry)
Console.WriteLine(ex.Message.ToString)
End Try
Next
End Sub
Private Function CheckTable(ByVal ColumnName As String) As Boolean
If _DataTable.Columns.Contains(ColumnName) Then
Return True
Else
_DataTable.Columns.Add(ColumnName)
Return False
End If
End Function
End Class

Invalid Cast Exception with Update Panel

On Button Click
Protected Sub btnSubmit_Click(sender As Object, e As System.EventArgs) Handles btnSubmit.Click
MsgBox("INSIDE")
If SocialAuthUser.IsLoggedIn Then
Dim accountId As Integer = BLL.getAccIDFromSocialAuthSession
Dim AlbumID As Integer = BLL.createAndReturnNewAlbumId(txtStoryTitle.Text.Trim, "")
Dim URL As String = BLL.getAlbumPicUrl(txtStoryTitle.Text.Trim)
Dim dt As New DataTable
dt.Columns.Add("PictureID")
dt.Columns.Add("AccountID")
dt.Columns.Add("AlbumID")
dt.Columns.Add("URL")
dt.Columns.Add("Thumbnail")
dt.Columns.Add("Description")
dt.Columns.Add("AlbumCover")
dt.Columns.Add("Tags")
dt.Columns.Add("Votes")
dt.Columns.Add("Abused")
dt.Columns.Add("isActive")
Dim Row As DataRow
Dim uniqueFileName As String = ""
If Session("ID") Is Nothing Then
lblMessage.Text = "You don't seem to have uploaded any pictures."
Exit Sub
Else
**Dim FileCount As Integer = Request.Form(Request.Form.Count - 2)**
Dim FileName, TargetName As String
Try
Dim Path As String = Server.MapPath(BLL.getAlbumPicUrl(txtStoryTitle.Text.Trim))
If Not IO.Directory.Exists(Path) Then
IO.Directory.CreateDirectory(Path)
End If
Dim StartIndex As Integer
Dim PicCount As Integer
For i As Integer = 0 To Request.Form.Count - 1
If Request.Form(i).ToLower.Contains("jpg") Or Request.Form(i).ToLower.Contains("gif") Or Request.Form(i).ToLower.Contains("png") Then
StartIndex = i + 1
Exit For
End If
Next
For i As Integer = StartIndex To Request.Form.Count - 4 Step 3
FileName = Request.Form(i)
'## If part here is not kaam ka..but still using it for worst case scenario
If IO.File.Exists(Path & FileName) Then
TargetName = Path & FileName
'MsgBox(TargetName & "--- 1")
Dim j As Integer = 1
While IO.File.Exists(TargetName)
TargetName = Path & IO.Path.GetFileNameWithoutExtension(FileName) & "(" & j & ")" & IO.Path.GetExtension(FileName)
j += 1
End While
Else
uniqueFileName = Guid.NewGuid.ToString & "__" & FileName
TargetName = Path & uniqueFileName
End If
IO.File.Move(Server.MapPath("~/TempUploads/" & Session("ID") & "/" & FileName), TargetName)
PicCount += 1
Row = dt.NewRow()
Row(1) = accountId
Row(2) = AlbumID
Row(3) = URL & uniqueFileName
Row(4) = ""
Row(5) = "No Desc"
Row(6) = "False"
Row(7) = ""
Row(8) = "0"
Row(9) = "0"
Row(10) = "True"
dt.Rows.Add(Row)
Next
If BLL.insertImagesIntoAlbum(dt) Then
lblMessage.Text = PicCount & IIf(PicCount = 1, " Picture", " Pictures") & " Saved!"
lblMessage.ForeColor = Drawing.Color.Black
Dim db As SqlDatabase = Connection.connection
Using cmd As DbCommand = db.GetSqlStringCommand("SELECT PictureID,URL FROM AlbumPictures WHERE AlbumID=#AlbumID AND AccountID=#AccountID")
db.AddInParameter(cmd, "AlbumID", Data.DbType.Int32, AlbumID)
db.AddInParameter(cmd, "AccountID", Data.DbType.Int32, accountId)
Using ds As DataSet = db.ExecuteDataSet(cmd)
If ds.Tables(0).Rows.Count > 0 Then
ListView1.DataSource = ds.Tables(0)
ListView1.DataBind()
Else
lblMessage.Text = "No Such Album Exists."
End If
End Using
End Using
'WebNavigator.GoToResponseRedirect(WebNavigator.URLFor.ReturnUrl("~/Memories/SortImages.aspx?id=" & AlbumID))
Else
'TODO:we'll show some error msg
End If
Catch ex As Exception
MsgBox(ex.Message)
lblMessage.Text = "Oo Poop!!"
End Try
End If
Else
WebNavigator.GoToResponseRedirect(WebNavigator.URLFor.LoginWithReturnUrl("~/Memories/CreateAlbum.aspx"))
Exit Sub
End If
End Sub
The above code works fine.I have added an Update Panel in the page to avoid post back, But when i add the button click as a trigger
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnSubmit" />
</Triggers>
in the update panel to avoid post back, i get the following error.This happens when i add the button click as a Trigger to the update panel.
The Request.Form returns a NameValueCollection which is accessible by the name of the key or the int indexer. It always returns a String and not an Integer.
Dim FileCount As String = Request.Form(Request.Form.Count - 2)
This is all intuition from the exception message, but on the line
FileCount As Integer = Request.Form(Request.Form.Count - 2)
It looks like Request.Form(Request.Form.Count - 2) is a string, and you're trying trying to assign a it to an integer type.
I don't know what you're trying to do, but the string looks like it contains "true" do you want the following?
FileCount As Integer += Boolean.Parse(Request.Form(Request.Form.Count - 2)) ? 1 : 0;

Adaptive a vba excel function to be recursive

Im having trouble converting a working solution that takes a directory folder as an input and outputs the filenames and other file attributes of files container in the folder into an excel spreadsheet to a recursive solution that also outputs the files contained in subfolders. I would greatly appreciate any help!
Sub GetFileList()
Dim strFolder As String
Dim varFileList As Variant
Dim FSO As Object, myFile As Object
Dim myResults As Variant
Dim l As Long
' Get the directory from the user
With Application.FileDialog(msoFileDialogFolderPicker)
.Show
If .SelectedItems.Count = 0 Then Exit Sub
'user cancelled
strFolder = .SelectedItems(1)
End With
' Get a list of all the files in this directory. ' Note that this isn't recursive... although it could be...
varFileList = fcnGetFileList(strFolder)
If Not IsArray(varFileList) Then
MsgBox "No files found.", vbInformation
Exit Sub
End If
' Now let's get all the details for these files ' and place them into an array so it's quick to dump to XL.
ReDim myResults(0 To UBound(varFileList) + 1, 0 To 5)
' place make some headers in the array
myResults(0, 0) = "Filename"
myResults(0, 1) = "Size"
myResults(0, 2) = "Created"
myResults(0, 3) = "Modified"
myResults(0, 4) = "Accessed"
myResults(0, 5) = "Full path"
Set FSO = CreateObject("Scripting.FileSystemObject")
' Loop through our files
For l = 0 To UBound(varFileList)
Set myFile = FSO.GetFile(CStr(varFileList(l)))
myResults(l + 1, 0) = CStr(varFileList(l))
myResults(l + 1, 1) = myFile.Size
myResults(l + 1, 2) = myFile.DateCreated
myResults(l + 1, 3) = myFile.DateLastModified
myResults(l + 1, 4) = myFile.DateLastAccessed
myResults(l + 1, 5) = myFile.Path
Next l
' Dump these to a worksheet
fcnDumpToWorksheet myResults
'tidy up
Set myFile = Nothing
Set FSO = Nothing
End Sub
Private Function fcnGetFileList(ByVal strPath As String, Optional strFilter As String) As Variant ' Returns a one dimensional array with filenames ' Otherwise returns False
Dim f As String
Dim i As Integer
Dim FileList() As String
If strFilter = "" Then strFilter = "."
Select Case Right$(strPath, 1)
Case "\", "/"
strPath = Left$(strPath, Len(strPath) - 1)
End Select
ReDim Preserve FileList(0)
f = Dir$(strPath & "\" & strFilter)
Do While Len(f) > 0
ReDim Preserve FileList(i) As String
FileList(i) = f
i = i + 1
f = Dir$()
Loop
If FileList(0) <> Empty Then
fcnGetFileList = FileList
Else
fcnGetFileList = False
End If
End Function
Private Sub fcnDumpToWorksheet(varData As Variant, Optional mySh As Worksheet)
Dim iSheetsInNew As Integer
Dim sh As Worksheet, wb As Workbook
Dim myColumnHeaders() As String
Dim l As Long, NoOfRows As Long
If mySh Is Nothing Then
'make a workbook if we didn't get a worksheet
iSheetsInNew = Application.SheetsInNewWorkbook
Application.SheetsInNewWorkbook = 1
Set wb = Application.Workbooks.Add
Application.SheetsInNewWorkbook = iSheetsInNew
Set sh = wb.Sheets(1)
Else
Set mySh = sh
End If
With sh
Range(.Cells(1, 1), .Cells(UBound(varData, 1) + 1, UBound(varData, 2) + 1)) = varData
.UsedRange.Columns.AutoFit
End With
Set sh = Nothing
Set wb = Nothing
End Sub
I've rewritten the code to pass your results array and a counter to the recursive function. The function fills the array and calls itself with any subfolders
Sub GetFileList()
Dim strFolder As String
Dim FSO As Object
Dim fsoFolder As Object
Dim myResults As Variant
Dim lCount As Long
Set FSO = CreateObject("Scripting.FileSystemObject")
' Get the directory from the user
With Application.FileDialog(msoFileDialogFolderPicker)
.Show
If .SelectedItems.Count = 0 Then Exit Sub
'user cancelled
strFolder = .SelectedItems(1)
End With
Set fsoFolder = FSO.GetFolder(strFolder)
'the variable dimension has to be the second one
ReDim myResults(0 To 5, 0 To 0)
' place make some headers in the array
myResults(0, 0) = "Filename"
myResults(1, 0) = "Size"
myResults(2, 0) = "Created"
myResults(3, 0) = "Modified"
myResults(4, 0) = "Accessed"
myResults(5, 0) = "Full path"
'Send the folder to the recursive function
FillFileList fsoFolder, myResults, lCount
' Dump these to a worksheet
fcnDumpToWorksheet myResults
'tidy up
Set FSO = Nothing
End Sub
Private Sub FillFileList(fsoFolder As Object, ByRef myResults As Variant, ByRef lCount As Long, Optional strFilter As String)
Dim i As Integer
Dim fsoFile As Object
Dim fsoSubFolder As Object
Dim fsoSubFolders As Object
'load the array with all the files
For Each fsoFile In fsoFolder.Files
lCount = lCount + 1
ReDim Preserve myResults(0 To 5, 0 To lCount)
myResults(0, lCount) = fsoFile.Name
myResults(1, lCount) = fsoFile.Size
myResults(2, lCount) = fsoFile.DateCreated
myResults(3, lCount) = fsoFile.DateLastModified
myResults(4, lCount) = fsoFile.DateLastAccessed
myResults(5, lCount) = fsoFile.Path
Next fsoFile
'recursively call this function with any subfolders
Set fsoSubFolders = fsoFolder.SubFolders
For Each fsoSubFolder In fsoSubFolders
FillFileList fsoSubFolder, myResults, lCount
Next fsoSubFolder
End Sub
Private Sub fcnDumpToWorksheet(varData As Variant, Optional mySh As Worksheet)
Dim iSheetsInNew As Integer
Dim sh As Worksheet, wb As Workbook
Dim myColumnHeaders() As String
Dim l As Long, NoOfRows As Long
If mySh Is Nothing Then
'make a workbook if we didn't get a worksheet
iSheetsInNew = Application.SheetsInNewWorkbook
Application.SheetsInNewWorkbook = 1
Set wb = Application.Workbooks.Add
Application.SheetsInNewWorkbook = iSheetsInNew
Set sh = wb.Sheets(1)
Else
Set mySh = sh
End If
'since we switched the array dimensions, have to transpose
With sh
Range(.Cells(1, 1), .Cells(UBound(varData, 2) + 1, UBound(varData, 1) + 1)) = _
Application.WorksheetFunction.Transpose(varData)
.UsedRange.Columns.AutoFit
End With
Set sh = Nothing
Set wb = Nothing
End Sub

Resources