将文件复制/移动到2个或更多目标文件夹中,如果文件名中有分隔符。

huangapple go评论147阅读模式
英文:

Move/copy a file into 2+ destination folders if there is a delimitator in the filename

问题

抱歉,代码部分我将保持原文不翻译。

英文:

I want to expand this vba script that moves files from an inbox folder to the correct destination folder by using variables from the filename to lookup the correct investment folder path for the file in Sharepoint and then subsequently moves the file to the destination folder. Currently, the vba script only works on a 1:1 ratio though, moving 1 document into 1 destination folder. I need it to also be able to move 1 document into multiple destination folders if needed [or rather, move the document into the 1 destination folder then save copies of it to any others]. The trigger would be the existence of a special delimiter in the filename separating destinations. That said, it would also be helpful if the original filename was updated to include only the investment name for each copy saved. For Example -

  1. Filename: 12901-01_Upside III_Carnegie;Carrington_CAS_2023.03.30.pdf
  2. Action 1: Move original file into the Carnegie investment folder and rename: 12901-01_Upside III_Carnegie \_CAS_2023.03.30.pdf
  3. Action 2: Save a copy of original file into the Carrington investment folder and rename: 12901-01_Upside III_Carrington_CAS_2023.03.30.pdf

There are few other nuances being considered in the full code, which you can see more pieces of in the screenshot below, but my main question is how to move a document multiple places if there is a delimitator in the filename. So, please keep in mind that I have only copied the sections of code below that I think are relevant to this question.

将文件复制/移动到2个或更多目标文件夹中,如果文件名中有分隔符。

将文件复制/移动到2个或更多目标文件夹中,如果文件名中有分隔符。

  1. Public TaxPath_12900 As String
  2. Public Investments As New collection
  3. Public LogDataCol As New collection
  4. Public LogDataBool As Boolean
  5. Public ClientCode As String
  6. Public ClientFolder As String
  7. Public FieldCountAdj As Integer
  8. Public ClientMapsFolder As String
  9. Public ClientLogFolder As String
  10. Public StopFlag As Boolean
  11. Function CheckBoxFileExists(ByVal filePath As String) As Boolean
  12. checks if file exists by searching for the filename in the folder and returns true or false
  13. CheckBoxFileExists = False
  14. Dim i As Integer
  15. Dim fso As Object
  16. Set fso = CreateObject("Scripting.fileSystemObject")
  17. For i = 0 To 4 'wait for 5 seconds total if needed
  18. If fso.FileExists(filePath) = False Then
  19. Application.Wait (Now + TimeValue("0:00:01"))
  20. Else
  21. CheckBoxFileExists = True
  22. Exit For
  23. End If
  24. Next i
  25. End Function
  26. Sub SetClientCodeVar()
  27. Select Case ClientCode
  28. Case "12900"
  29. ClientFolder = " C:\Box\Client II\12901 Fund\Acct\Client Document Inbox\”
  30. ClientMapsFolder = "C:\Box\Client II\12901 Fund\Acct\Client Maps\ "
  31. ClientLogFolder = "C:\Box\Client II\12901 Fund\Acct\Client Log (SharePoint Upload)\"
  32. FieldCountAdj = 1
  33. TaxPath_12900 = " C:\Box\Client II\12901 Fund\Tax\Shared\tax docs\downloaded docs\”
  34. End Select
  35. End Sub
  36. Function PopulateListBoxFromCSV(ListBox As MSForms.ListBox, clientName As String)
  37. 'needs "ms scripting runtime" and "Microsoft VBScript Regular Expressions 5.5"
  38. ClientCode = Mid(clientName, 2, InStr(clientName, "]") - 2)
  39. Call SetClientCodeVar
  40. Dim filePath As String
  41. filePath = ClientMapsFolder & ClientCode & "_MAP.CSV"
  42. Dim fso As New FileSystemObject
  43. Dim ts As TextStream
  44. Dim row As Long
  45. Dim arrData() As String
  46. 'open the file
  47. Set ts = fso.OpenTextFile(filePath, ForReading)
  48. UserForm1.Label_RefreshTime.Caption = "Mapping Refresh: " & FileDateTime(filePath)
  49. 'Open the file
  50. 'Open filePath For Input As #1
  51. ' Read the data from the file
  52. Dim line As String
  53. Dim rowString As String
  54. Dim dupeRecords As Boolean
  55. dupeRecords = False
  56. Do While Not ts.AtEndOfStream
  57. row = row + 1
  58. rowString = ts.ReadLine
  59. line = ReplaceCSVDelimiter(rowString)
  60. arrData = Split(line, "|")
  61. 'populate collection
  62. Dim investment As clsInvestmentList
  63. Set investment = New clsInvestmentList
  64. If ItemExists(arrData(0) & "-" & arrData(2), Investments) = False Then
  65. investment.RowNum = row
  66. investment.fundID = UCase(arrData(0))
  67. investment.FundName = arrData(1)
  68. investment.InvestmentID = UCase(arrData(2))
  69. investment.InvestmentName = arrData(3)
  70. investment.ProjectID = arrData(4)
  71. investment.BaseFolderPath = arrData(5)
  72. investment.StatementFolders = arrData(6)
  73. investment.InvestActivityFolders = arrData(7)
  74. Investments.Add investment, arrData(0) & "-" & arrData(2)
  75. Else
  76. dupeRecords = True
  77. End If
  78. Loop
  79. Call PopulateListBox(ListBox)
  80. ts.Close
  81. If dupeRecords = True Then MsgBox ("Note: Your sharepoint list contains duplicate records for the same Fund ID & Investment ID pairing. Please remove duplicate records from sharepoint " & ClientCode & "_MAP.")
  82. End Function
  83. Function PopulateListBox(ListBox As MSForms.ListBox, Optional filterFundID As String = "")
  84. Dim item As Variant
  85. Dim i As Long
  86. i = 0
  87. For Each item In Investments
  88. If filterFundID <> "" Then
  89. If filterFundID <> item.fundID Then
  90. GoTo NextIteration
  91. End If
  92. End If
  93. ' Add the data to the list box
  94. ListBox.AddItem item.RowNum
  95. ListBox.List(i, 1) = item.fundID
  96. ListBox.List(i, 2) = item.FundName
  97. ListBox.List(i, 3) = item.InvestmentID
  98. ListBox.List(i, 4) = item.InvestmentName
  99. ListBox.List(i, 5) = item.ProjectID
  100. i = i + 1
  101. NextIteration:
  102. Next item
  103. End Function
  104. Sub ExportDiagnostics()
  105. Dim wb As Workbook
  106. Dim ws As Worksheet
  107. Dim filePath As Variant
  108. filePath = Application.GetSaveAsFilename("Folder Diagnostics " & ClientCode, fileFilter:="Excel Files (*.xlsx), *.xlsx", Title:="Select Destination Folder")
  109. If filePath = False Then Exit Sub
  110. Set wb = Workbooks.Add
  111. Set ws = wb.Worksheets(1)
  112. Dim i As Long
  113. Dim UFLB As MSForms.ListBox
  114. Set UFLB = UserForm2.ListBox1
  115. For i = 0 To UFLB.ListCount - 1
  116. ws.Cells(i + 1, 1).value = UFLB.List(i, 0)
  117. ws.Cells(i + 1, 2).value = UFLB.List(i, 1)
  118. ws.Cells(i + 1, 3).value = UFLB.List(i, 2)
  119. ws.Cells(i + 1, 4).value = UFLB.List(i, 3)
  120. ws.Cells(i + 1, 5).value = UFLB.List(i, 4)
  121. ws.Cells(i + 1, 6).value = UFLB.List(i, 5)
  122. ws.Cells(i + 1, 7).value = UFLB.List(i, 8)
  123. ws.Cells(i + 1, 8).value = UFLB.List(i, 6)
  124. ws.Cells(i + 1, 9).value = UFLB.List(i, 7)
  125. Next i
  126. Call ResizeSheet(ws)
  127. wb.SaveAs filePath
  128. wb.Close
  129. MsgBox ("List exported to Excel.")
  130. End Sub
  131. Function CreateBrowserFormPath() As collection
  132. Dim tempCollection As New collection
  133. Dim str As String
  134. Dim itemNo As Integer
  135. Dim UF As UserForm
  136. Set UF = UserForm1
  137. itemNo = Int(UF.ListBox1.List(UF.ListBox1.ListIndex, 0))
  138. str = Investments.item(itemNo).BaseFolderPath
  139. If Right(str, 1) <> "\" Then str = str & "\"
  140. tempCollection.Add str
  141. Select Case UF.ComboBox1.Text
  142. Case "FS & PCAPs"
  143. str = str & Investments.item(Int(itemNo)).StatementFolders & "\"
  144. If UF.ComboBox2.Text <> "" Then
  145. str = str & UF.ComboBox2.Text & "\"
  146. If UF.ComboBox3.Text <> "" Then str = str & UF.ComboBox3.Text & "\"
  147. End If
  148. Case "Investment Activity"
  149. str = str & Investments.item(itemNo).InvestActivityFolders & "\"
  150. End Select
  151. tempCollection.Add str
  152. Set CreateBrowserFormPath = tempCollection
  153. End Function
  154. Function GetFileMetaData(UFLB As MSForms.ListBox, Optional filterFundID As String = "")
  155. Dim oFSO As Object
  156. Dim oFolder As Object
  157. Dim oFile As Object
  158. Set oFSO = CreateObject("Scripting.FileSystemObject")
  159. Set oFolder = oFSO.GetFolder(ClientFolder)
  160. If CheckBoxFolderExists(ClientFolder) = False Then Exit Function
  161. Dim fileNameArr() As String
  162. Dim tempStr As String
  163. Dim item As String
  164. Dim sType As String
  165. Dim i As Integer
  166. Dim charCount As Integer
  167. i = 0
  168. For Each oFile In oFolder.Files
  169. If LCase(Right(oFile.Name, 4)) <> ".pdf" Then GoTo NextIteration
  170. fileNameArr = Split(Replace(LCase(oFile.Name), ".pdf", ""), "_")
  171. If filterFundID <> "" Then
  172. If filterFundID <> UCase(fileNameArr(0)) Then
  173. GoTo NextIteration
  174. End If
  175. End If
  176. charCount = Len(oFile.Name) - Len(Replace(oFile.Name, "_", ""))
  177. If charCount <> 3 + FieldCountAdj Then GoTo NextIteration
  178. UFLB.AddItem oFile.Name
  179. ' we want to use the investment ID variable below to retrieve Fund Name / Fund ID from our "investments" collection
  180. UFLB.List(i, 1) = oFile.DateLastModified
  181. If ItemExists(fileNameArr(0) & "-" & fileNameArr(1), Investments) = False Then
  182. UFLB.List(i, 2) = ""
  183. UFLB.List(i, 3) = ""
  184. UFLB.List(i, 4) = ""
  185. UFLB.List(i, 5) = ""
  186. UFLB.List(i, 6) = ""
  187. UFLB.List(i, 7) = ""
  188. i = i + 1
  189. GoTo NextIteration
  190. End If
  191. UFLB.List(i, 2) = UCase(fileNameArr(0))
  192. UFLB.List(i, 3) = Investments.item(fileNameArr(0) & "-" & fileNameArr(1)).FundName
  193. UFLB.List(i, 4) = UCase(fileNameArr(1))
  194. UFLB.List(i, 5) = Investments.item(fileNameArr(0) & "-" & fileNameArr(1)).InvestmentName
  195. Select Case UCase(fileNameArr(2 + FieldCountAdj))
  196. Case "CAS"
  197. sType = "Capital Account Statement"
  198. Case "FS"
  199. sType = "Financial Statements"
  200. Case "CD"
  201. sType = "Distribution"
  202. Case "CC"
  203. sType = "Contribution"
  204. Case "K-1"
  205. sType = "Tax"
  206. End Select
  207. UFLB.List(i, 6) = sType
  208. UFLB.List(i, 7) = ConvertDateFormat(fileNameArr(3 + FieldCountAdj))
  209. On Error GoTo 0
  210. i = i + 1
  211. NextIteration:
  212. Next oFile
  213. End Function
  214. Function ItemExists(ByRef value As Variant, ByRef collection As collection) As Boolean
  215. On Error Resume Next
  216. ItemExists = False
  217. ItemExists = Not (collection.item(value) Is Nothing)
  218. On Error GoTo 0
  219. End Function
  220. Function CreateFormPath() As Collection
  221. 'function returns a collection object
  222. Dim tempCollection As New Collection 'Declares a variable named "tempCollection" to hold a new instance of the Collection object
  223. Dim strBase As String
  224. Dim strDocType As String
  225. Dim strYear As String
  226. Dim strQtr As String 'Declares variables to hold different parts of the path
  227. Dim itemKey As String 'Declares a variable named "itemKey" to hold a string
  228. Dim UF As UserForm 'Declares a variable named "UF" to hold a reference to a UserForm
  229. Set UF = UserForm3 'Assigns the reference of "UserForm3" to the "UF" variable
  230. itemKey = UF.ListBox1.List(UF.ListBox1.ListIndex, 2) & "-" & UF.ListBox1.List(UF.ListBox1.ListIndex, 4)
  231. 'Constructs the "itemKey" by concatenating two values from ListBox1 on the UserForm
  232. If ItemExists(itemKey, Investments) = False Then 'Checks if "itemKey" doesnt exist in the "Investments" collection
  233. tempCollection.Add ""
  234. tempCollection.Add ""
  235. tempCollection.Add ""
  236. tempCollection.Add "" 'Adds four empty strings to the "tempCollection"
  237. Set CreateFormPath = tempCollection 'Sets the function's return value to the "tempCollection".
  238. Exit Function
  239. End If
  240. strBase = Investments.Item(itemKey).BaseFolderPath 'Gets "BaseFolderPath" from "Investments" collection using the "itemKey"
  241. Dim tempDates
  242. tempDates = EndOfQuarter(CDate(UF.ListBox1.List(UF.ListBox1.ListIndex, 7)))
  243. 'Retrieves a date value from ListBox1 on the UserForm and calculates the end of the quarter using the "EndOfQuarter" function
  244. If Right(strBase, 1) <> "\" Then strBase = strBase & "\" 'Checks if "strBase" doesn't end with a \ & adds one if needed
  245. Select Case UF.ListBox1.List(UF.ListBox1.ListIndex, 6) 'begins case stmt based on value in UserForm ListBox1
  246. Case "Capital Account Statement", "Financial Statements"'If ListBox1 value is "Capital Account Statement" or "Financial Statements", execute code block:
  247. tempCollection.Add "CASFS" 'Adds "CASFS" to the "tempCollection"
  248. strDocType = Investments.Item(itemKey).StatementFolders & "\"
  249. 'Appends the "StatementFolders" property from the "Investments" collection to "strDocType"
  250. strYear = Left(tempDates, 4) & "\" 'Retrieves leftmost 4 characters of "tempDates" and appends a \ to "strYear"
  251. strQtr = Right(tempDates, 2) & "\" 'Retrieves rightmost 2 characters of "tempDates" and appends a \ to "strQtr"
  252. Case "Distribution", "Contribution" 'If ListBox1 value is "Distribution" or "Contribution", execute code block:
  253. tempCollection.Add "CF" 'Adds "CF" to the "tempCollection"
  254. strDocType = Investments.Item(itemKey).InvestActivityFolders & "\"
  255. 'Appends the "InvestActivityFolders" property from the "Investments" collection to "strDocType".
  256. strYear = Left(tempDates, 4) & "\" 'Retrieves leftmost 4 characters of "tempDates" and appends a \ to "strYear"
  257. strQtr = Right(tempDates, 2) & "\" 'Retrieves rightmost 2 characters of "tempDates" and appends a \ to "strQtr"
  258. Case "Tax" 'If ListBox1's selected value is "Tax", the following code block is executed
  259. tempCollection.Add "Tax" ' Adds "Tax" to the "tempCollection"
  260. Select Case ClientCode 'Begins another Select Case statement based on the value of "ClientCode"
  261. Case "12900" 'If "ClientCode" is "12900", the following code block is executed
  262. strBase = TaxPath_12900 'Overrides the value of "strBase" with a predefined path
  263. End Select
  264. Case "" 'If ListBox1's selected value is empty, the following code block is executed
  265. tempCollection.Add "" 'Adds an empty string to the "tempCollection"
  266. End Select
  267. tempCollection.Add strBase 'Adds year base to the "tempCollection"
  268. tempCollection.Add strDocType 'Adds year doc type to the "tempCollection"
  269. tempCollection.Add strYear 'Adds year string to the "tempCollection"
  270. tempCollection.Add strQtr 'Adds quarter string to the "tempCollection"
  271. Set CreateFormPath = tempCollection 'Sets the function's return value to the "tempCollection"
  272. End Function
  273. Function MoveClientFiles(SourceFileName As String, ByVal DestinFileName As String)
  274. If Right(LCase(DestinFileName), 4) <> ".pdf" Then Exit Function
  275. Dim fso As Object
  276. Set fso = CreateObject("Scripting.Filesystemobject")
  277. Dim i As Integer
  278. Dim tempStr As String
  279. Dim tempVer As String
  280. tempStr = Left(DestinFileName, Len(DestinFileName) - 4)
  281. tempVer = ""
  282. i = 2
  283. Do Until CheckBoxFileExists(tempStr & tempVer & ".pdf") = False
  284. tempVer = "_V" & i
  285. Loop
  286. DestinFileName = tempStr & tempVer & ".pdf"
  287. fso.MoveFile Source:=SourceFileName, Destination:=DestinFileName
  288. Dim UFLB As MSForms.ListBox
  289. Set UFLB = UserForm3.ListBox1
  290. 'populate collection
  291. Dim logData As clsInvestmentList
  292. Set logData = New clsInvestmentList
  293. logData.LogTitle = UFLB.List(UFLB.ListIndex, 0)
  294. logData.LogUserName = Application.UserName
  295. logData.LogTimeStamp = Now()
  296. logData.LogFundID = UFLB.List(UFLB.ListIndex, 2)
  297. logData.LogFundName = UFLB.List(UFLB.ListIndex, 3)
  298. logData.LogInvestmentID = UFLB.List(UFLB.ListIndex, 4)
  299. logData.LogInvestmentName = UFLB.List(UFLB.ListIndex, 5)
  300. logData.LogDestinationFolder = DestinFileName
  301. logData.LogStatementType = UFLB.List(UFLB.ListIndex, 6)
  302. logData.LogStatementDate = UFLB.List(UFLB.ListIndex, 7)
  303. logData.LogFileDateModified = UFLB.List(UFLB.ListIndex, 1)
  304. LogDataCol.Add logData
  305. MsgBox ("File moved successfully! Details added to session log.")
  306. UserForm3.ListBox1.RemoveItem UserForm3.ListBox1.ListIndex
  307. End Function

答案1

得分: 1

以下是您代码示例的翻译部分:

  1. 您的代码示例非常长,因此我将为您提供一个示例,展示如何执行您的“主要问题”(即“如何在文件名中存在分隔符的情况下将文档移动到多个位置”),而不是重写您的代码。
  2. 以下代码已经注释,以解释每个部分的作用,然后您可以使用相关行更新您现有的代码(变量名称需要更改以匹配您的代码)。请注意,此代码(即此“Test”方法)是可运行的示例,因此如果您想查看它的工作原理,可以逐步执行代码:
  3. Sub Test()
  4. Dim text As String
  5. text = "12901-01_Upside III_Carnegie;Carrington_CAS_2023.03.30.pdf"
  6. ' 将单个文本分割成以“;”分隔的文件名
  7. Dim filenames As Variant
  8. filenames = Split(text, ";") ' 假定分号仅用于分隔名称,不会出现在文件名中
  9. ' 迭代每个文件名...如果不存在“;”,则此循环只会执行1次,否则会执行多次
  10. Dim index As Long, doingForFirstFile As Boolean
  11. For index = LBound(filenames) To UBound(filenames)
  12. ' 我们是否正在处理第一个文件名?
  13. doingForFirstFile = index = LBound(filenames)
  14. If doingForFirstFile Then
  15. Debug.Print Now, "第一个文件名是 '" & filenames(index) & "'"
  16. ' 在此处放置处理第一个文件的代码
  17. Else
  18. Debug.Print Now, "后续文件名是 '" & filenames(index) & "'"
  19. ' 在此处放置制作后续副本的代码...由于您正在使用FSO,所以可以使用其.CopyFile方法
  20. End If
  21. Next index
  22. End Sub

有关如何使用FSO的.CopyFile方法,请参阅以下链接:

  1. <details>
  2. <summary>英文:</summary>
  3. Your code sample is quite lengthy and so I am giving you an example of how your &#39;main question&#39; (i.e. &quot;how to move a document multiple places if there is a delimitator in the filename&quot;) could be done rather than re-writing your code.
  4. The following code is commented to explain what each part does, you can then update your existing code with the relevant lines (the variable names will need to be changed to match your code). Note that the code (i.e. this `Test` method) is a runnable example so you can step through the code if you want to see how it works:

Sub Test()
Dim text As String
text = "12901-01_Upside III_Carnegie;Carrington_CAS_2023.03.30.pdf"

  1. &#39; split the single piece of text into file names delimited by &quot;;&quot;
  2. Dim filenames As Variant
  3. filenames = Split(text, &quot;;&quot;) &#39; assumes semi-colon is only used to delimite names and can never appear within a file name
  4. &#39; iterate over each file name ... this loop can happen 1 time if no &quot;;&quot; is present, otherwise multiple times
  5. Dim index As Long, doingForFirstFile As Boolean
  6. For index = LBound(filenames) To UBound(filenames)
  7. &#39; are we working on the first file name?
  8. doingForFirstFile = index = LBound(filenames)
  9. If doingForFirstFile Then
  10. Debug.Print Now, &quot;The first file name is &#39;&quot; &amp; filenames(index) &amp; &quot;&#39;&quot;
  11. &#39; put your code to process the first copy of the file here
  12. Else
  13. Debug.Print Now, &quot;A subsequent file name is &#39;&quot; &amp; filenames(index) &amp; &quot;&#39;&quot;
  14. &#39; put your code to make subsequent copies here ... as you are using FSO then you can use its .CopyFile method
  15. End If
  16. Next index

End Sub

  1. For how to use the .CopyFile method of FSO, see [this link](https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/copyfile-method) and [this link](https://learn.microsoft.com/en-us/previous-versions/tn-archive/ee198744(v=technet.10))
  2. </details>

huangapple
  • 本文由 发表于 2023年8月10日 13:57:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76872972.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定