• 2

VBA問題(從多個檔案抓取資料貼到單一檔案的不同sheet中)

各位高手好,想請問一個VBA的問題
目的:希望將同一資料夾中,不同檔案的特定sheet資料彙整到單一檔案的不同sheet中
以下是我目前寫的語法以及遇到的問題
遇到的問題
1.有沒有辦法不打開檔案就成功複製資料
2.雖然有設定StrFileName 但是在試跑巨集時並沒有發揮作用
即會一直貼相同的內容到不同分頁

請各位高手幫忙了QAQ

目前寫的VBA語法
Sub test2()
 
Dim wc As Workbook
Set wc = ThisWorkbook
 
Dim wb As Object
Set wb = ThisWorkbook.Sheets(1)
 
Dim shell
Dim StrPathName As String
Dim StrFileName As String
 
Set shell = CreateObject("shell.application") _
.browseforfolder(0, "choose a folder", 0, ThisWorkbook.Path)
 
If shell Is Nothing Then
End
Else
StrPathName = shell.Items.Item.Path
End If
 
StrFileName = Dir(StrPathName & "\*POP表*.xls")
 
 
Application.ScreenUpdating = False
 
' Open the workbook with the filename
Dim wk As fil
Set wk = Workbooks.Open
 
' Declare the range variables
Dim rgSource As Range, rgDestination As Range
 
'count file amount
Dim mypath As String, myFile As String, myname As String, n As Integer
mypath = ActiveWorkbook.Path & "\"
myFile = "*.xls"
myname = Dir(mypath & myFile)
Do While myname <> ""
n = n + 1
myname = Dir
Loop
 
'set loop info
Dim b As Integer, a As Integer
a = 1
b = n - 1
 
'set loop
Do While StrFileName <> ""
wb.Activate
For a = 1 To b
 
' Get the source and destination range
Set rgSource = wk.Worksheets(2).Range("A7:I96")
Set rgDestination = ThisWorkbook.Worksheets(a).Range("A1")
 
' Clear existing destination data
rgDestination.CurrentRegion.ClearContents
 
' Copy the data
rgSource.Copy
rgDestination.PasteSpecial xlPasteValues
 
Next a
 
StrFileName = Dir()
 
a = a + 1
Loop
 
End Sub
2020-09-16 18:13 發佈
文章關鍵字 VBA 問題 檔案
1.有沒有辦法不打開檔案就成功複製資料


您的問題一,所謂的「不打開」,是指「真的」不去動該文件(open)?
幾個方向思考:
1.一般來說,如果使用VBA,open該檔案,取得其內容資料後,再命令其關閉,時間很短暫,使用者不大感覺到,這樣您是否可以接受?

Sub bb()
Dim src As Workbook
Set src = Workbooks.Open("f:\new.xlsx", True, True)
ThisWorkbook.Activate
'以下抓取資料
............
src.Close
End Sub

檔案不是太大的話,一般使用者應該還能接受。
以下是網路上找到,有關的實際影片解說視頻(內容大同小異):


2.如果堅持不open該檔,可以使用連結參照檔案的方式,在VBA或儲存格中,公式位置參照直接列出檔案路徑即可。
不過這種方式取得的內容,有可能是錯誤的(因未開啟,所以excel似乎就沒有對該檔案進行:開啟後自動重算或更新?)

3.另闢蹊徑~~使用其他方式來連接該檔:
ADO and the Excel ODBC driver(把Excel檔案當資料庫用),或是python(不知是否能做到您的需求)
有google到一個網址,裡面有段話:
You can use ADO and the Excel ODBC driver to treat closed workbooks as databases. You can then use SQL to retrieve data. But it assumes that you have information laid out in tables with table headings. AFAIK that's the only way to deal with a spreadsheet without opening it.

ADO參考

若有興趣,您可以研究看看。

至於您的問題二:
meu00 wrote:
雖然有設定StrFileName 但是......

雖然我未能實際執行您的code,但個人注意到,您有2處用到dir()
meu00 wrote:
StrFileName = Dir(StrPathName & "\*POP表*.xls")

在該sub內約20行左右。

倒數第4~5行:
StrFileName = Dir()


照理來說,最後這個StrFileName = Dir(),應該會是要去找下一個檔案;但你在這2者之間,又用了一次Dir

.......
myname = Dir(mypath & myFile)
Do While myname <> ""
n = n + 1
myname = Dir
Loop
........

這部分您最好檢查一下,因為會造成錯誤發生,或是讀取檔案不正確。(更別說後續貼上正確資料了)

簡單直接的做法,是把你的第一個使用Dir:

StrFileName = Dir(StrPathName & "\*POP表*.xls")

這句挪到中間那第2個Dir()之後。這樣2個StrFileName 在進行Dir查詢時,中間沒有突然的「打岔」,才能順利傳回所有(用迴圈)檔案名稱。

以上簡單意見,提供您參考囉。(如果問題2能因此順利解決,也麻煩您抽空回應一下囉。)
Der,misser1
meu00 wrote:
' Open the workbook with the filename
Dim wk As fil
Set wk = Workbooks.Open


另外,fil 這個是? ?(新的定義?...... 哈)
Der,misser1
花一點時間再看一下,發現原本第一次用Dir()的這句:
StrFileName = Dir(StrPathName & "\*POP表*.xls")
如果要往下移到第二次Dir()之後:

myname = Dir(mypath & myFile)
Do While myname <> ""
n = n + 1
myname = Dir
Loop
'-------(移到這?)
'set loop info
Dim b As Integer, a As Integer

那麼原本第一次那句位置下的幾句也得一起往下移:

'這幾句也得一起往下
' Open the workbook with the filename
Dim wk As fil
Set wk = Workbooks.Open

(因為我猜您上面那句open,是要開啟StrPathName ,所以這幾句位置仍得在原本StrFileName = Dir(StrPathName & "\*POP表*.xls")之後)

然後,
Dim wk As fil
Set wk = Workbooks.Open
這2句語法是否得修正一下?

本來有想是不是幫您小修一下VBA內容讓其可行,可是看了後我有點搞混:您是要把哪些檔案(指定資料夾內所有xls?)的內容複製到哪?(第一次Dir()找的StrFileName = Dir(StrPathName & "\*POP表*.xls")?)......但您後面的迴圈要處理的也是StrFileName,而不是myname?(所以我有點迷糊了)

可能得請您再多敘述清楚:從哪些copy到哪....這樣才有辦法幫您下手。........再不然還是得等版上其他前輩高手出手幫您囉。(發現很多都是自己「想太多」搞不懂,但前輩高手們總是能「秒懂」並即時給出解決方法.........唉,差距啊。)
Der,misser1
又或者,是您把要找來開啟的檔案,誤打成myname(*.xls)和StrFileName(*POP表*.xls)2種區別,但其實只有一個(一種)來源?.........都是要貼到thisworkbook(不在搜尋的結果之列)裡?
Der,misser1
meu00 wrote:
1.有沒有辦法不打開檔案就成功複製資料
2.雖然有設定StrFileName 但是在試跑巨集時並沒有發揮作用


1、有,2樓說的方法,但不適合您用,用copy比較方便
2、整個架構都寫錯了

這個CreateObject("shell.application").browseforfolder物件,回傳值就包含檔名、路徑
不需要再使用dir


Sub test()

Call delsheet '只保留工作表1,刪掉其它所有工作表

Dim Get_Path As Object, Default_Path As Variant, xls_fullpath As Variant, pop As Workbook

Default_Path = ThisWorkbook.Path
Set Get_Path = CreateObject("Shell.Application").BrowseForFolder(0, "choose a folder", &H201, Default_Path)

If Get_Path Is Nothing Then
MsgBox "???"
Exit Sub
End If

Application.DisplayAlerts = False
For Each xls_fullpath In Get_Path.items
DoEvents
If xls_fullpath.Path Like "*pop表*.xls" And Not xls_fullpath.isfolder Then
Sheets.Add(After:=Sheets(Sheets.Count)).Name = "_" & xls_fullpath.Name & "_"

Set pop = Workbooks.Open(xls_fullpath.Path, , False)
'請自行練習修改資料範圍
pop.Sheets("工作表1").Range("a1:a3").Copy ThisWorkbook.Sheets("_" & xls_fullpath.Name & "_").Range("a1:a3")
pop.Close 1
Set pop = Nothing

End If
Next
Application.DisplayAlerts = True


Set Get_Path = Nothing

End Sub



Sub delsheet()

Dim delsheet() As Variant, i As Integer, j As Integer
ReDim delsheet(1 To Worksheets.Count)
Application.DisplayAlerts = False

For i = 1 To Worksheets.Count
If Worksheets(i).Name <> "工作表1" Then '預設不刪除工作表1
j = j + 1
delsheet(j) = Worksheets(i).Name
End If
Next
If j = 0 Then Exit Sub
ReDim Preserve delsheet(1 To j)
Worksheets(delsheet).Delete

Application.DisplayAlerts = True

End Sub

misser wrote:
又或者,是您把要找來(恕刪)


首先謝謝高手熱心的回答
我想應該是我說的不夠清楚
本身表達能力有些問題

其實我的目的就和您說的一樣
來源檔案只有一種就是資料夾中檔名有包含POP表的檔案(檔案數量會超過一個)
然後統一貼到一個檔案不同sheet中(檔名不包含POP表)

另外您提供的dir調整有試過了,的確有解決問題謝謝您
meu00 wrote:
來源檔案只有一種就是資料夾中檔名有包含POP表的檔案


所以我就是被您「騙」暈囉,難怪,我就想,您為何要先用StrFileName來找 *POP表*.xls,後面又用myname來找"*.xls".....架構真的有奇怪到,所以無法確認怎麼幫您改。

不過s大直接就看穿您的「企圖」,還幫您完成了範例。而且也提醒您,那個物件已經有包含回傳值(整個資料夾下的檔案資料),後面您就無須再逐一用Dir()去抓下一個檔案資料囉。

meu00 wrote:
另外您提供的dir調整有試過了,的確有解決問題謝謝您

太好了,能幫上您的忙。

不過可能您得再評估一下整個架構流程,有需要除錯也會比較清楚.........s大修改的,您可以多多參考。

祝您工作順利。
Der,misser1
snare wrote:
1、有,2樓說的方法(恕刪)


謝謝高手指導
目前還有一個問題想要詢問
因為希望貼上的資料格式型態為"值"
使用了以下方法卻是失敗的
請問有甚麼解法嗎?
失敗的原因是"Class Range的Select方法失敗"
是因為選擇的範圍有誤嗎?
以下是我根據您的語法進行添加和修改的內容
不好意思再麻煩您了

Set pop = Workbooks.Open(xls_fullpath.Path, , False)
pop.Sheets(2).Range("A7:I96").Copy Destination:=ThisWorkbook.Sheets(xls_fullpath.Name).Range("A1:I90")
ThisWorkbook.Sheets(xls_fullpath.Name).Range("A1:I90").Select
Selection.PasteSpecial Paste:=xlPasteValues
pop.Close 1
Set pop = Nothing
misser wrote:
所以我就是被您「騙」(恕刪)


感謝您的建議
其實我VBA完全是瞎子摸象般自學
在網路上找資料東拼西湊
語法概念的基礎幾乎為0
看樣子得找時間好好學習了
  • 2
內文搜尋
X
評分
評分
複製連結
Mobile01提醒您
您目前瀏覽的是行動版網頁
是否切換到電腦版網頁呢?