Board logo

標題: [發問] 新手發問有關活頁中的圖片操作 [打印本頁]

作者: baconbacons    時間: 2014-4-3 17:38     標題: Range( ) 中有變數 要再指定給物件變數的問題

以下程式碼目的是要將特定資料夾中的相片插入到指定儲存格並依儲存格大小調整相片尺寸
目前問題出在於「Set  picNumRng = Range("A" & (25 * (k - 1) + 5 - Application.WorksheetFunction.RoundUp((k - 1) / 2, 0)))」
上述程式作用是依序於儲存格「A5,A29,A54,A78,A103,A127…」輸入相片流水號「1,2,3,4,5,6…」
執行後會出現執行階段錯誤「應用程式或物件定義上的錯誤」
監看了「Range(…) 」發現並不會呈現A5 所以也沒辦法指定給picNumRng
細看了一下 (25 * (k - 1) + 5 - Application.WorksheetFunction.RoundUp((k - 1) / 2, 0))的結果確實是可以算出我需要的格數
但是與 Range("A" …)  無法結合成我需要的A5 是何原因?
--------------------------------------------------------------------------------------------
Sub photoConv()
    Dim myFSO As New FileSystemObject
    Dim myPath As String, myPic As Object
    Dim E As Range, picNumRng As Object
    Dim myPhoto As String, countPhoto As String
    Dim i As Integer, j As Integer, k As Integer

    myPath = ThisWorkbook.Path                                                                                            '確認活頁簿所在路徑
    myPhoto = Dir(myPath & "\" & "原始相片" & "\" & "*.jpg")
    countPhoto = myFSO.GetFolder(myPath & "\" & "原始相片").Files.Count - 1    '取得相片數量
    If myPhoto <> "" Then                                                                                                           '資料夾中有相片時複製表格
        j = 50
        For i = 1 To ((countPhoto + 1) \ 2 - 1)
            Rows("1:49").Copy                                                                                                           '複製表格
            ActiveSheet.Paste Cells(j, 1)
            j = j + 49
        Next i
        
        For k = 1 To countPhoto                                                                                                   '輸入相片編號
            Set picNumRng = Range("A" & (25 * (k - 1) + 5 - Application.WorksheetFunction.RoundUp((k - 1) / 2, 0)))
            picNumRng = k
                For Each E In picNumRng                                                                                          '逐一處理儲存格
                    Set myPic = ActiveSheet.Pictures.Insert(myPath & E & ".jpg")                '插入與儲存格同名的相片檔
                        With myPic
                            .ShapeRange.LockAspectRatio = msoFalse
                            .Left = E.Cells(1, 2).Left
                            .Top = E.Cells(1, 2).Top
                            .Width = E.Cells(1, 2).Width
                            .Height = E.Cells(1, 2).Height
                        End With
                Next
        Next
    Else
        MsgBox "資料夾中沒有相片"
    End If
End Sub
作者: GBKEE    時間: 2014-4-3 20:50

回復 1# baconbacons
2003版可以的
  1. Option Explicit
  2. Sub ex()
  3.     Dim k, picNumRng As Range
  4.     For k = 1 To 50 'countPhoto                       '輸入相片編號
  5.         Set picNumRng = Range("A" & (25 * (k - 1) + 5 - Application.WorksheetFunction.RoundUp((k - 1) / 2, 0)))
  6.         picNumRng.Select            
  7.     Next
  8. End Sub
複製代碼

作者: baconbacons    時間: 2014-4-7 14:01

回復 2# GBKEE
GBKEE 大:
                     原先的程式碼本來在輸入編號就沒問題 只是在插入相片時會有錯誤產生
                     我將原始的程式碼改成你建議的方式 還是出現一樣的錯誤問題
                     還能怎麼修改呢?
作者: GBKEE    時間: 2014-4-7 15:35

回復 3# baconbacons
我的2003版可以的需請有2010版的相助.
作者: baconbacons    時間: 2014-4-7 19:01

回復 4# GBKEE
請教 GBKEE 大:
你所謂的2003可以是指可以輸入流水編號,還是說連插入圖片也可以?
因為我執行你建議程式碼 只有選取符合的儲存格 最後停在k=50的那個儲存格

另外請教一個 For Each... Next 的觀念問題?
是否這個用法只針對「未運算執行巨集程式前」之「符合條件的所有物件集合」?
換言之 就是以我自己的這個例子來說
Set picNumRng = Range("A" & (25 * (k - 1) + 5 - Application.WorksheetFunction.RoundUp((k - 1) / 2, 0)))
我的物件集合picNumRng是在For Next迴圈執行之後 才會「逐一」運算產生符合的物件
而不是在運算之前就已經完全得知所有的物件
在運用此種逐一產生的物件是否就必須再搭配For Next用法  而不是 For Each... Next
不知道這樣表達夠不夠清楚
作者: c_c_lai    時間: 2014-4-7 19:34

回復 5# baconbacons
試試這個:
  1. Sub Ex2()
  2.     Dim myFSO As New FileSystemObject
  3.     Dim myPath As String, myPic As Object
  4.     Dim myPhoto As String, countPhoto As Long       '  countPhoto As String
  5.     Dim picNumRng As Object
  6.     Dim k As Integer

  7.     myPath = ThisWorkbook.Path                                                                                            '  確認活頁簿所在路徑
  8.     countPhoto = myFSO.GetFolder(myPath & "\" & "原始相片").Files.Count          '  取得相片數量
  9.     myPhoto = Dir(myPath & "\" & "原始相片" & "\" & "*.jpg")
  10.    
  11.     If myPhoto <> "" Then                                                                                                           '  資料夾中有相片時複製表格
  12.         For k = 1 To countPhoto                                                                                                   '  輸入相片編號
  13.             Set picNumRng = Range("A" & (25 * (k - 1) + 5 - Application.WorksheetFunction.RoundUp((k - 1) / 2, 0)))
  14.             
  15.             ActiveSheet.Pictures.Insert (myPath & "\" & "原始相片" & "\" & myPhoto)              '  插入與儲存格同名的相片檔
  16.             With ActiveSheet.Shapes(k)
  17.                 .LockAspectRatio = msoFalse
  18.                 .Top = picNumRng.Top
  19.                 .Left = picNumRng.Left
  20.                 .Width = 75
  21.                 .Height = 100
  22.             End With
  23.             myPhoto = Dir
  24.         Next
  25.     Else
  26.         MsgBox "資料夾中沒有相片"
  27.     End If
  28. End Sub
複製代碼

作者: GBKEE    時間: 2014-4-7 21:12

回復 5# baconbacons
  1. Option Explicit
  2. Sub Ex()
  3.     Dim E As Variant, K As Integer, picNumRng As Range
  4.     For Each E In Workbooks     'Workbook物件 的集合物件
  5.         MsgBox E.Name
  6.     Next
  7.     For Each E In Range("A5:C5") 'Cells物件 的集合物件
  8.         MsgBox E.Address
  9.     Next
  10.     For K = 1 To 50     '跑50次迴圈
  11.         Set picNumRng = Range("A" & (25 * (K - 1) + 5 - Application.WorksheetFunction.RoundUp((K - 1) / 2, 0)))
  12.         For Each E In picNumRng 'Cells物件 的集合物件
  13.             MsgBox E.Address
  14.         Next
  15.     Next
  16. End Sub
複製代碼

作者: baconbacons    時間: 2014-4-7 22:53

回復 6# c_c_lai
c_c_lai 大:
經過修改後測試 確實可以執行 但是因為使用「ActiveSheet.Shapes(k)」的用法的關係
由於我在活頁中也設計了一個執行按鈕 所以這個用法會去抓這個按鈕的圖示 再貼到我指定儲存格
(如果沒有設計該按鈕的話 您所建議的程式碼確實都是可以符合我的需求的)
這個部分我比不知道怎麼改善 所以就試著使用GBKEE大的建議方法
不過 還是感謝c_c_lai 大的協助 讓我學到 .Shapes(k) 以及 myPhoto = Dir  的用法
感激…
作者: baconbacons    時間: 2014-4-7 22:58

回復 7# GBKEE
GBKEE 大:
感謝清楚的範例解決我的觀念問題  我也利用這個小例子改善我原先的程式碼
確實已經可以執行了 萬分感謝
以下也貼上我修改後的程式碼  讓有需要的人也可以學習
如果能讓程式碼更簡潔的話 也請其他大大指教
----------------------------------------------------------------------------------------------
Sub photoConv1()
    Dim myFSO As New FileSystemObject
    Dim myPath As String
    Dim picNumRng As Range, myPic As Object
    Dim myPhoto As String, countPhoto As String
    Dim E As Variant
    Dim i As Integer, j As Integer, k As Integer
   
    myPath = ThisWorkbook.Path                                                                                                          '確認活頁簿所在路徑
    myPhoto = Dir(myPath & "\" & "原始相片" & "\" & "*.jpg")                                                    '圖片檔路徑
    countPhoto = myFSO.GetFolder(myPath & "\" & "原始相片").Files.Count - 1                  '取得相片數量
    If myPhoto <> "" Then                                                                                                                         '資料夾中有相片時複製表格
        j = 50
        ActiveSheet.Cells(27, 3).Value = ActiveSheet.Cells(3, 3).Value
        ActiveSheet.Cells(28, 7).Value = ActiveSheet.Cells(4, 7).Value
        ActiveSheet.Cells(27, 7).Value = ActiveSheet.Cells(3, 7).Value
        ActiveSheet.Cells(27, 8).Value = ActiveSheet.Cells(3, 8).Value
        ActiveSheet.Cells(27, 10).Value = ActiveSheet.Cells(3, 10).Value
        ActiveSheet.Cells(27, 12).Value = ActiveSheet.Cells(3, 12).Value
        ActiveSheet.Cells(27, 14).Value = ActiveSheet.Cells(3, 14).Value
        
        For i = 1 To ((countPhoto + 1) \ 2 - 1)
            Rows("1:49").Copy                                                                                                                          '複製表格
            ActiveSheet.Paste Cells(j, 1)
            j = j + 49
        Next i
        
        For k = 1 To countPhoto
            Set picNumRng = Range("A" & (25 * (k - 1) + 5 - Application.WorksheetFunction.RoundUp((k - 1) / 2, 0)))
                picNumRng = k                                                                                                                            '輸入相片編號
                For Each E In picNumRng
                Set myPic = ActiveSheet.Pictures.Insert(myPath & "\" & "原始相片" & "\" & E & ".jpg")   '插入與儲存格同名的相片檔
                With myPic
                    .ShapeRange.LockAspectRatio = msoFalse
                    .Top = picNumRng.Offset(0, 1).Top
                    .Left = picNumRng.Offset(0, 1).Left
                    .Width = picNumRng.Offset(0, 1).MergeArea.Width
                    .Height = picNumRng.Offset(0, 1).MergeArea.Height
                End With
                Next
        Next k
    Else
        MsgBox "資料夾中沒有相片"
    End If
    Set picNumRng = Nothing
    Set myPic = Nothing
End Sub
作者: GBKEE    時間: 2014-4-8 06:24

本帖最後由 GBKEE 於 2014-4-8 06:27 編輯

回復 9# baconbacons
Dim myFSO As New FileSystemObject
需設定 引用項目  Microsoft scripting runtime
  1. Option Explicit
  2. Sub Ex()
  3.     Dim myFSO As New FileSystemObject
  4.     Dim picNumRng As Range
  5.     Dim E As Variant, k As Integer, P As Object               
  6.     With ActiveSheet        '指定工作表
  7.         .Pictures.Delete    '刪除 所有相片
  8.         For Each P In myFSO.GetFolder("d:\相片\74年").Files         '檔案物件集合
  9.             If UCase(P) Like "*.JPG" Then    'P 檔案物件 傳回完整路徑名稱 , Like 比對是否有".JPG"的字元
  10.                 k = k + 1
  11.                 Set picNumRng = .Range("A" & (25 * (k - 1) + 5 - Application.WorksheetFunction.RoundUp((k - 1) / 2, 0)))
  12.                 With picNumRng
  13.                     .Rows("1:1").RowHeight = 100                   '調整 高度
  14.                     .Columns("A:A").ColumnWidth = 25               '調整 寬度
  15.                 End With
  16.                 With .Pictures.Insert(P)                           '插入 P 檔案物件(相片)
  17.                     .ShapeRange.LockAspectRatio = msoFalse
  18.                     .Top = picNumRng.Top
  19.                     .Left = picNumRng.Left
  20.                     .Width = picNumRng.Width
  21.                     .Height = picNumRng.Height
  22.                 End With
  23.             End If
  24.         Next
  25.     End With
  26.     MsgBox "資料夾中" & IIf(k > 0, "共" & k & "張", "沒有") & "相片"
  27. End Sub
複製代碼

作者: baconbacons    時間: 2014-4-8 16:42

回復 10# GBKEE
果然可以用更精簡的方法來撰寫 待我慢慢消化了解  感謝…
想請教Set picNumRng = .Range("A" & (25 * (k - 1) + 5 - Application.WorksheetFunction.RoundUp((k - 1) / 2, 0)))這行程式碼
為何Range前方又多了一個「.」用意為何?

另外請教GBKEE大:
因為我的表格是預設表格(列高必須是固定的)所以才會使用下列程式碼
        For i = 1 To ((countPhoto + 1) \ 2 - 1)
            Rows("1:49").Copy                                                  '複製表格
            ActiveSheet.Paste Cells(j, 1)
            j = j + 49
        Next i
會使用這方式是因為全列複製才能保持列高 如果以range範圍來複製表格範圍 列高會不一致
但此種方法的缺點就是 在我表格右手邊設計的按鈕也會一併複製 也就是複製幾次表格 就出現幾個按鈕
能否解決複製表格同時又可保持列高 而且巨集按鈕又不會影響到?
作者: GBKEE    時間: 2014-4-8 18:06

本帖最後由 GBKEE 於 2014-4-8 20:04 編輯

回復 11# baconbacons
  1. Option Explicit
  2. Sub Ex()
  3.     Dim i, countPhoto, Rng As Range
  4.     countPhoto = 50
  5.     Set Rng = Rows("1:49")
  6.     For i = Rng.Rows.Count To (countPhoto + 1) * Rng.Rows.Count + 1 Step Rng.Rows.Count '間隔 Rng的列數=49
  7.         Rng.Copy                        '複製表格
  8.         With ActiveSheet.Cells(i + 1, 1)
  9.         'With 陳述式 在一個單一物件或一個使用者自訂型態上執行一系列的陳述式。
  10.         '加上 . 為這單一物件的屬性或方法
  11.             .PasteSpecial Paste:=xlPasteFormats                     '這單一物件:  僅貼上格式
  12.             .Resize(Rng.Rows.Count, Rng.Columns.Count) = Rng.Value   '這單一物件:  貼上數值
  13.         End With
  14.     Next
  15. End Sub
複製代碼

作者: baconbacons    時間: 2014-4-8 20:04

回復 12# GBKEE
GBKEE 大:
嘗試過後沒問題 感謝
正在試著了解你的寫法中
作者: baconbacons    時間: 2014-4-9 17:12     標題: 新手發問有關活頁中的圖片操作

請教各位前輩 在設計自己需求的程式 遇到問題時會怎麼解決?
1.可以巨集錄製時,先錄製來看使用何方法或物件
2.無法錄製時,到F1說明以關鍵字搜尋看有無類似說明
3.GOOGLE大神搜尋法

假設現在我的問題是要「對調」活頁中現存的圖片
我先用錄製巨集方法 得知EXCEL是用下列程式碼來選取圖片
「ActiveSheet.Shapes.Range(Array("Picture 4")).Select」
所以我也比照此法 設定變數後 再進行兩個圖片的對調
但是卻失敗了
由於先前所學知道插入圖片是ActiveSheet.Pictures.Insert
再來到說明以Pictures為關鍵字去搜尋 可是也找不到
最後的GOOGLE大神 也因為不知道該怎麼下關鍵字 找不到符合需求的
有沒有前輩願意分享經驗
作者: GBKEE    時間: 2014-4-9 17:53

回復 1# baconbacons

請附檔看看
作者: baconbacons    時間: 2014-4-10 09:15

[attach]17969[/attach]回復 2# GBKEE
預設情形說明:
由於表格是複製編號1及編號2的表格而來 所以每次新增相片會多出兩個空白相片儲存格
如果我只是要新增1張相片的話 就必須將下方的相片往上遞補至新的表格
就效率上來說 似乎是下列方法2比較有效率
1.假設新增插入編號11的相片,刪除原先編號11之後的相片及表格,重新複製所需表格,新增編號11相片再讀入資料夾的相片自編號12開始貼
2.假設新增插入編號11的相片,複製新表格(2空白相片儲存格)插入,新增編號11相片再將活頁中的相片依序往上遞補1張

以上說明若有說明不清楚的 煩請再指教
作者: baconbacons    時間: 2014-4-10 10:41

回復 3# baconbacons
歹勢 請針對工作表3(相片冊)的程式碼為主  其他還只是測試階段用
作者: GBKEE    時間: 2014-4-10 14:18

本帖最後由 GBKEE 於 2014-4-10 16:09 編輯

回復 16# baconbacons

由於表格是複製編號1及編號2的表格而來 所以每次新增相片會多出兩個空白相片儲存格
Q:為何一次要,複製編號1及編號2的表格

1.假設新增插入編號11的相片,刪除原先編號11之後的相片及表格,重新複製所需表格,新增編號11相片再讀入資料夾的相片自編號12開始貼
Q: 新增插入編號11的相片,為何是:刪除原先編號11之後的相片及表格,而不包含原先編號11相片及表格,
    為何是:自編號12開始貼,不是自編號11開始貼

2.假設新增插入編號11的相片,複製新表格(2空白相片儲存格)插入,新增編號11相片再將活頁中的相片依序往上遞補1張
Q:為何要: 複製新表格(2空白相片儲存格)插入,多一空白位置爾後將相片依序往上遞補1張(多此一舉)

是這樣嗎?
  1. Sub Ex()
  2.     Dim myFSO As New FileSystemObject
  3.     Dim Rng As Range, i As Integer
  4.     Dim myPath As String
  5.     Dim E As Variant
  6.     myPath = ThisWorkbook.Path & "\原始相片"            '相片的資料夾
  7.     If myFSO.GetFolder(myPath).Files.Count > 0 Then     '有檔案
  8.         With ActiveSheet                                '指定工作表
  9.             .Pictures.Delete                            '刪除所有相片
  10.             Set Rng = .[A3:O25]                         '相片表格
  11.             .Rows("26:" & .UsedRange.Rows.Count).Clear   '清除 第一張相片以後的表格
  12.             For Each E In myFSO.GetFolder(myPath).Files '檔案物件集合
  13.                 If UCase(E) Like "*.JPG" Then           'E (檔案物件)傳回完整路徑名稱 , Like 比對是否有".JPG"的字元
  14.                     With Rng.Offset((i) * Rng.Rows.Count + (i * 1)) '相片的表格位置
  15.                         If i > 0 Then                    '第2張後
  16.                             Rng.Copy
  17.                             .PasteSpecial xlPasteFormats
  18.                             .Value = Rng.Value
  19.                             .Range("A3") = i + 1         '相片的表格位置的Range("A3")
  20.                         End If
  21.                         .Range("C22") = E
  22.                         .Range("B3").Select              '相片的表格位置的Range("B3")
  23.                     End With
  24.                     With .Pictures.Insert(E)                                      '插入P檔案物件(相片)
  25.                         .ShapeRange.LockAspectRatio = msoFalse
  26.                         .Top = Selection(1, 1).Top
  27.                         .Left = Selection(1, 1).Left
  28.                         .Width = Selection.Width
  29.                         .Height = Selection.Height
  30.                     End With
  31.                     i = i + 1
  32.                 End If
  33.             Next
  34.         End With
  35.     End If
  36.     MsgBox myPath & " 資料夾中" & IIf(i > 0, "共" & i & "張", "沒有") & "相片"
  37. End Sub
複製代碼

作者: baconbacons    時間: 2014-4-18 08:39

回復 18# GBKEE
GBKEE大:歹勢讓您久等了,回應如下

由於表格是複製編號1及編號2的表格而來 所以每次新增相片會多出兩個空白相片儲存格
Q:為何一次要,複製編號1及編號2的表格
A:因為兩個空白表格可以剛好完整一頁,且每頁最上方表格為標題列,如果只插入單一空白表格,接下來的表格都會跑掉
1.假設新增插入編號11的相片,刪除原先編號11之後的相片及表格,重新複製所需表格,新增編號11相片再讀入資料夾的相片自編號12開始貼
Q: 新增插入編號11的相片,為何是:刪除原先編號11之後的相片及表格,而不包含原先編號11相片及表格,為何是:自編號12開始貼,不是自編號11開始貼
A:新增插入編號11意即保留編號1~10的相片,將原先編號11之後的相片及表格順移一格,但由於上述兩空白填滿一頁的限制,所以必須新增新頁(兩空白表格),欲新增的編號11相俧置於編號11,原先的編號11就下移至編號12,接下來的相片就依序接上,這樣不知道能否理解…
2.假設新增插入編號11的相片,複製新表格(2空白相片儲存格)插入,新增編號11相片再將活頁中的相片依序往上遞補1張
Q:為何要: 複製新表格(2空白相片儲存格)插入,多一空白位置爾後將相片依序往上遞補1張(多此一舉)
A:如上述答案

所建議程式碼待我研究一下再請教




歡迎光臨 麻辣家族討論版版 (http://forum.twbts.com/)