anhtuan1066
Thành viên gạo cội




- Tham gia
- 10/3/07
- Bài viết
- 5,802
- Được thích
- 6,912
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim mySel As Range
On Error Resume Next
If Not Intersect(Range("KeyCells"), Target) Is Nothing Then
Set mySel = Selection
ActiveSheet.Shapes(mySel.Address & "Final").Delete
ActiveSheet.Shapes(mySel.Value).Copy
With mySel
.Offset(0, 2).PasteSpecial
Selection.Name = .Address & "Final"
Selection.Left = .Offset(0, 2).Left: Selection.Top = .Offset(0, 2).Top
Selection.Width = .Offset(0, 2).Width: Selection.Height = .Offset(0, 2).Height
End With
End If
mySel.Select
End Sub
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim PicRng As Range, Pos As String
Application.ScreenUpdating = False
On Error Resume Next
If Not Intersect([B5:B8], Target) Is Nothing Then
Set PicRng = Range("G1").CurrentRegion '<--- Dat ten cho vung tra cuu hinh
Pos = WorksheetFunction.VLookup(Target, PicRng, 2, 0) '<--- Xac dinh vi trí chua file hinh tren PC
ActiveSheet.Shapes(Target.Address).Delete '<--- Xoa hinh da dat ten truoc do
With ActiveSheet.Pictures.Insert(Pos) '<--- Chen hinh moi
.Name = Target.Address '<--- Dat ten cho hinh moi chính là dia chi cell
.Left = Target(1, 0).Left: .Top = Target(1, 0).Top '<--- Dinh vi cho hinh
.Width = Target(1, 0).Width: .Height = Target(1, 0).Height '<--- Dinh chieu rong, cao cho hinh
End With
End If
Application.ScreenUpdating = True
End Sub
Anh Tuấn Ơ i ! Cho đứa Em Ngốc Nghếc này hỏi Anh thê m một chút nữa vêề đ oạn code chạy hình trong excel của Anh nhé ;(Set PicRng = Range("G1").CurrentRegion '<--- Dat ten cho vung tra cuu hinh) Anh dặt tê n cho vùng tra cứu hình là G1 vậy Anh vao dau de dat vay.
Them nua ( Pos = WorksheetFunction.VLookup(Target, PicRng, 2, 0) '<--- Xac dinh vi trí chua file hinh tren PC) day la duong dan den file hinh vay Em muon khai bao lai duong dan khac thi vao dau de khai vay Anh. Nho Anh chi dum Em voi nha . cam on Anh that nhieu
Lại tiếp tục cải tiến:
Bỏ luôn mấy hình mẩu (lấy hình dựa vào đường dẩn)PHP:Option Explicit Private Sub Worksheet_Change(ByVal Target As Range) Dim PicRng As Range, Pos As String Application.ScreenUpdating = False On Error Resume Next If Not Intersect([B5:B8], Target) Is Nothing Then Set PicRng = Range("G1").CurrentRegion '<--- Dat ten cho vung tra cuu hinh Pos = WorksheetFunction.VLookup(Target, PicRng, 2, 0) '<--- Xac dinh vi trí chua file hinh tren PC ActiveSheet.Shapes(Target.Address).Delete '<--- Xoa hinh da dat ten truoc do With ActiveSheet.Pictures.Insert(Pos) '<--- Chen hinh moi .Name = Target.Address '<--- Dat ten cho hinh moi chính là dia chi cell .Left = Target(1, 0).Left: .Top = Target(1, 0).Top '<--- Dinh vi cho hinh .Width = Target(1, 0).Width: .Height = Target(1, 0).Height '<--- Dinh chieu rong, cao cho hinh End With End If Application.ScreenUpdating = True End Sub
Các bạn có thể dựa vào file này để làm PicForm (khá đơn giãn)
Các bác pro cho hỏi: trong file của bác Tuấn thì cần phải có địa chỉ của ảnh thì mới Vlookup được. Nếu file ảnh và file excel cùng 1 folder và chuyển folder này từ địa chỉ này qua địa chỉ khác thì phải thay đổi địa chỉ file ở vùng vlookup. Làm thế nào để thay đổi địa chỉ mà không phải update lại địa chỉ?
Khi xưa ta bé ta ngu...
Ngày trước download file này ở các trang nước ngoài về, chỉ đơn giản thấy hay thì đưa lên... giờ xem lại code thấy.. buồn cười (code dài dòng, lúc chạy thì cà giật) ===> đâu cứ code nước ngoài viết là hay
He... he...
Sửa lại đây
File này dùng 3 hình mẫu có sẳn trong sheet, các bạn có thể cải tiến, thậm chí không cần mấy hình mẩu này tôi nghĩ cũng ko có vấn đề (nếu trong máy tính của ta đã có sẳn)PHP:Option Explicit Private Sub Worksheet_Change(ByVal Target As Range) Dim mySel As Range On Error Resume Next If Not Intersect(Range("KeyCells"), Target) Is Nothing Then Set mySel = Selection ActiveSheet.Shapes(mySel.Address & "Final").Delete ActiveSheet.Shapes(mySel.Value).Copy With mySel .Offset(0, 2).PasteSpecial Selection.Name = .Address & "Final" Selection.Left = .Offset(0, 2).Left: Selection.Top = .Offset(0, 2).Top Selection.Width = .Offset(0, 2).Width: Selection.Height = .Offset(0, 2).Height End With End If mySel.Select End Sub
(Record quá trình Insert hình rồi chỉnh lại code)
Bạn cho toàn bộ code này vào sheet nhé:Làm sao để thêm được hình khác theo bài này nữa vậy bạn anhtuan1066
Private Sub Worksheet_Change(ByVal Target As Range)
Dim pic As Picture
On Error Resume Next
If Not Intersect(Range("B5:B10"), Target) Is Nothing Then
If Target.Count = 1 Then
With Target.Parent
.Pictures(Target.Address).Delete
Set pic = .Pictures(Target.Value)
End With
If Not pic Is Nothing Then
pic.Copy
Target.Offset(, 2).PasteSpecial
With Selection
.Name = Target.Address
.ShapeRange.LockAspectRatio = msoFalse
.Left = Target.Offset(, 2).Left: .Top = Target.Offset(, 2).Top
.Width = Target.Offset(, 2).Width: .Height = Target.Offset(, 2).Height
End With
End If
End If
End If
Target.Select
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim rCel As Range, pic As Picture, arr(), n As Long
On Error Resume Next
If Not Intersect(Range("B5:B10"), Target) Is Nothing Then
If Target.Count = 1 Then
For Each pic In Target.Parent.Pictures
If Not (pic.Name Like "$*$*") Then
n = n + 1
ReDim Preserve arr(1 To n)
arr(n) = pic.Name
End If
Next
If IsArray(arr) Then
With Target.Validation
.Delete
.Add 3, , , Join(arr, ",")
End With
End If
End If
End If
End Sub
Bạn cho toàn bộ code này vào sheet nhé
Cám ơn thày Anh tuấn ! thày cho hỏi liệu có thể phóng to ảnh lên vài lần khi rê chuột đến được không ? vì như thế dữ liệu dòng và cột chỉ cần nhỏ thôi . Khi cần xem ảnh ta rê chuột vào ảnh được phóng to để cho dễ nhìn .Lại tiếp tục cải tiến:
Bỏ luôn mấy hình mẩu (lấy hình dựa vào đường dẩn)PHP:Option Explicit Private Sub Worksheet_Change(ByVal Target As Range) Dim PicRng As Range, Pos As String Application.ScreenUpdating = False On Error Resume Next If Not Intersect([B5:B8], Target) Is Nothing Then Set PicRng = Range("G1").CurrentRegion '<--- Dat ten cho vung tra cuu hinh Pos = WorksheetFunction.VLookup(Target, PicRng, 2, 0) '<--- Xac dinh vi trí chua file hinh tren PC ActiveSheet.Shapes(Target.Address).Delete '<--- Xoa hinh da dat ten truoc do With ActiveSheet.Pictures.Insert(Pos) '<--- Chen hinh moi .Name = Target.Address '<--- Dat ten cho hinh moi chính là dia chi cell .Left = Target(1, 0).Left: .Top = Target(1, 0).Top '<--- Dinh vi cho hinh .Width = Target(1, 0).Width: .Height = Target(1, 0).Height '<--- Dinh chieu rong, cao cho hinh End With End If Application.ScreenUpdating = True End Sub
Các bạn có thể dựa vào file này để làm PicForm (khá đơn giãn)
Cám ơn thày Anh tuấn ! thày cho hỏi liệu có thể phóng to ảnh lên vài lần khi rê chuột đến được không ? vì như thế dữ liệu dòng và cột chỉ cần nhỏ thôi . Khi cần xem ảnh ta rê chuột vào ảnh được phóng to để cho dễ nhìn .
Chính xác là thế! Nếu không, chẳng lẽ có 2 code sự kiện Change trong cùng 1 sheet sao? Nó báo lỗi liềnThay cho toàn bộ code cũ hả bạn ???
Có lẽ nhà em hỏi chưa chuẩn thì đúng hơn, không phải "Rê chuột" đến , mà là "di chuyển chuột đến" thì hình tự động phóng to, khi chuột di chuyển đến ô khác thì nó trở lại trạng thái cũ . Điều nữa là thày có thể kết hợp lấy hyferlink ảnh tự động luôn thì tốt quá vì hyferlink thủ công , nếu nhiều ảnh thì cũng khá vất. Xin cám ơn thày .Rê chuột vào để phóng to thì khó. Ta có thể thay bằng: Click chuột vào ảnh để phóng to <--- Cái này quá dễ, record macro quá trình thay đổi size hình để có code
Rê chuột đến hay di chuyển chuột đến thì cũng như nhau thôi. Tóm lại: Picture không có sự kiện nàyCó lẽ nhà em hỏi chưa chuẩn thì đúng hơn, không phải "Rê chuột" đến , mà là "di chuyển chuột đến" thì hình tự động phóng to, khi chuột di chuyển đến ô khác thì nó trở lại trạng thái cũ
Hyperlink ảnh tự động nghĩa là sao?Điều nữa là thày có thể kết hợp lấy hyferlink ảnh tự động luôn thì tốt quá vì hyferlink thủ công , nếu nhiều ảnh thì cũng khá vất. Xin cám ơn thày .
Rê chuột đến hay di chuyển chuột đến thì cũng như nhau thôi. Tóm lại: Picture không có sự kiện này
Ta chỉ có thể điều khiển hình phóng to, thu nhỏ khi ta dùng chuột CLICK VÀO HÌNH thôi
***
Xin lỗi thày, vì link của ảnh mầu xanh nên nhà em tưởng phải Hyperlink đến file ảnh . Nói để diến đạt chính xác thật khó, nhà em đính kèm tập tin nhờ thày giúp . code phóng to, thu nhỏ nhà em làm rồi, nó hoạt động tốt, nhưng nhà em loay hoay mãi để nó tự động thực hiện khi di chuyển chuột đến các ô có chứa địa chỉ ảnh mà không được. Mong thày xem giúp vì nhà em trình độ VBA kiểu ăn đong nên khó quá . Không phải ta cần sự kiện của ảnh mà là của cell thày ạ, tức là sự kiện để chạy 2 sub trên,làm sao để đia chỉ trong code thay đổi theo chuột là được . Không biết ý tưởng của nhà em thế có được không nữa ? Nghe có vẻ kỳ kỳ , mong thay xem giúp và hồi âm . Biết thày không thích gọi là "Thày", nhưng 1 ngày là thày mà 1 chữ cũng là thày mà . Vả lại học thày bao nhiêu là chữ .
Yêu cầu của bạn nếu làm thật kỹ cũng không phải dễ dàng gìNói để diến đạt chính xác thật khó, nhà em đính kèm tập tin nhờ thày giúp
Cám ơn thày! Đúng là code quá trởi luôn . Thày viết code như nhà em viết chính tả , khiếp thật . Nếu nhà em chép lại lượng code vậy chắc chưa xong . Nhà nhà em đã text thử , nói chung code lấy ảnh và compic ảnh chay tốt , riêng code ShpResize và chỉ thấy chớp màn hình và ảnh chỉ lướt qua rồi tắt . Theo em, hình như code làm việc tôt, chỉ thiếu câu lệnh gì đó . Về nguyên tắc là khi chạy code ShpResize thì ảnh đựợc phóng to, sau khi xem ảnh , chỉ sau khi di chuyển trỏ sang cell khác thì code trở về trạng thái cũ mới chạy , thày kiểm tra giúp nhà em với ạ . theo cái kiến thức con con của mình, nhà em cảm thấy thế không biết có phải không , thày thông cảm .Yêu cầu của bạn nếu làm thật kỹ cũng không phải dễ dàng gì
Bạn xem file đính kèm và test thử nha
(code quá trời luôn!)
Quên dặn bạn:Cám ơn thày! Đúng là code quá trởi luôn . Thày viết code như nhà em viết chính tả , khiếp thật . Nếu nhà em chép lại lượng code vậy chắc chưa xong . Nhà em đã text thử , nói chung code lấy ảnh và compic ảnh chay tốt , riêng code ShpResize và ShpReset chỉ thấy chớp màn hình và ảnh chỉ lướt qua rồi tắt . Theo em, hình như code làm việc tôt, chỉ thiếu câu lệnh gì đó . Về nguyên tắc là khi chạy code ShpResize thì ảnh đựợc phóng to, sau khi xem ảnh , chỉ sau khi di chuyển trỏ sang cell khác thì code ShpReset mới chạy . Nhưng hình như nó chạy 2 code tức thì nên ảnh chỉ chớp 1 cái rồi tắt, thày kiểm tra giúp nhà em với ạ . theo cái kiến thức con con của mình, nhà em cảm thấy thế không biết có phải không , thày thông cảm .
Cám ơn thày! Do thấy tập tin đuôi .xls nên nhà em mở bằng Excel 2003 nên nó sinh lỗi vậy . Nhà em mở bằng Excel 2010 tốt rồi ạ, cám ơn thày .Quên dặn bạn:
- Đừng bấm Alt + F8, chọn Sub để chạy gì cả
- Code được thiết kế tự động hóa hoàn toàn: Click chuột vào hình sẽ phóng to, click lần nữa sẽ thu nhỏ. Hoặc ta click chuột ra khỏi hình (chọn 1 cell nào đó) thì hình cũng sẽ được reset
- Khi chon Validation, nếu đường dẫn tại cell F1 không chưa hình nào (tức file không tồn tại) thì lập tức cửa sổ chọn Folder sẽ hiện ra cho bạn chọn lại thư mục chứa hình
- Bạn cũng có thể chủ động bấm vào nút Select Folder để chọn đường dẫn
vân vân... Từ từ khám khá nha. Code tren vẫn chưa được hay đâu (tại viết hơi vội)
Ngoài ra: Tôi dùng Excel 2010 nên không chắc trên Excel 2003 sẽ chạy thế nào
Tức là bạn muốn khi bấm nút Select Folder thì ảnh chèn luôn?Cám ơn thày ! Nhà em đã text thử code chạy tốt trên excel 2010, nhưng hiện nhà em muốn thày giúp thêm chút nữa là :
- Chẳng hạn khi chọn folder ảnh thì ảnh tự động chèn vào các ô theo số lượng ảnh trong folder đó . Khi cần đổi ảnh thì mới chon list trong từng ô .
Sub SelectFolder()
Dim arr, vFolder, [COLOR=#ff0000]pic, Target As Range[/COLOR]
[COLOR=#ff0000] Dim lR As Long[/COLOR]
[COLOR=#ff0000] Dim PicPath As String[/COLOR]
On Error Resume Next
vFolder = CreateObject("Shell.Application").BrowseForFolder(0, "", 1).Self.Path
If TypeName(vFolder) = "String" Then
If Right(vFolder, 1) <> "\" Then vFolder = vFolder & "\"
arr = FilesFoldersList(vFolder, True, "*.jpg", False)
If IsArray(arr) Then
aFiles = arr
sFolder = CStr(vFolder)
Range("F1") = sFolder
[COLOR=#ff0000] For Each pic In arr[/COLOR]
[COLOR=#ff0000] PicPath = sFolder & CStr(pic)[/COLOR]
[COLOR=#ff0000] InsertPic PicPath, Target, "ShpResize"[/COLOR]
[COLOR=#ff0000] Set Target = Range("A5").Offset(lR)[/COLOR]
[COLOR=#ff0000] lR = lR + 1[/COLOR]
[COLOR=#ff0000] Next[/COLOR]
Range("F1").Select
End If
End If
End Sub
Sub InsertPic(ByVal PicPath As String, ByVal Target As Range, Optional ByVal Action As String = "")
On Error Resume Next
Target.Parent.Pictures(Target.Address).Delete
With Target.Parent.Pictures.Insert(PicPath)
.Name = Target.Address
.ShapeRange.LockAspectRatio = msoFalse
.Left = Target.Left: .Top = Target.Top
.Width = Target.Width: .Height = Target.Height
.OnAction = Action
End With
End Sub
Không phải là tôi cố tình viết cho Excel 2010 mà là vì tôi không có bản Office 2003 để test nên không biết được lỗi phát sinh từ đâu- Thày có thế sửa code để có thể chạy cả ở Excel 2003 được không ạ ? vì khi ta gửi dữ liệu cho người khác , họ sử dụng Excel 2003 thì code phóng to ảnh bị lỗi ạ ?
Mong hồi âm từ thày! Xin cám ơn thày !
Set pic = Sheet1.Pictures(Application.Caller)
Nó báo lỗi tại dòng màu xanh đậm trên ạ !
Bạn thử thay Sheet1 bằng ActiveSheet xem sao. Nhưng thử gửi cái file đó lên xem, biết đâu nó cũng không phải lỗi tại đó.Ảnh nằm trong sheet1 mà thày, tức là nếu chạy trên Excel 2010 thì chạy tốt, nhưng ghi với đuôi .xls thì nó không chạy .
Lỗi này chỉ có thể có khi: Bạn chạy trực tiếp sub trên bằng cách Alt + F8 để chọn Sub thay vì click vào hìnhCám ơn thày ! Nó báo lỗi tại dòng màu xanh đậm trên ạ !Mã:Sub ShpResize() Dim pic As Picture Dim bMark As Boolean [COLOR=#0000ff][B] Set pic = Sheet1.Pictures(Application.Caller)[/B][/COLOR] With pic.ShapeRange bMark = (Len(.AlternativeText) > 0) If bMark = False Then .ScaleWidth 5, msoFalse, msoScaleFromMiddle .ScaleHeight 5, msoFalse, msoScaleFromMiddle .AlternativeText = "TRUE" .ZOrder msoBringToFront Else .Left = Range(.Name).Left: .Top = Range(.Name).Top .Width = Range(.Name).Width: .Height = Range(.Name).Height .AlternativeText = vbNullString End If End With End Sub
Xin lỗi thày, giờ nhà em mới vào mạng được . Tình hình cụ thể thế này ạ .Lỗi này chỉ có thể có khi: Bạn chạy trực tiếp sub trên bằng cách Alt + F8 để chọn Sub thay vì click vào hình
Còn lại, Application.Caller chẳng liên quan gì đến version của office cả (Excel 2003 cũng dùng được)
Thay Activesheet vào Sheet1 vẫn vậy ạ !Bạn thử thay Sheet1 bằng ActiveSheet xem sao. Nhưng thử gửi cái file đó lên xem, biết đâu nó cũng không phải lỗi tại đó.
Xin lỗi thày, giờ nhà em mới vào mạng được . Tình hình cụ thể thế này ạ .
Sau khi xóa dòng lệnh "on Error resume next" và click vào hình thì nó xuất hiện hộp thông báo lỗi :
'Run-time Error 1004'
Methot 'Pictures' of object '_Worksheet' Failed
và 4 nút . Nút Continue mờ và 3 nút End và Debug và Help . Click vào nút Debug thì xuất hiện code và dòng lệnh trên bị bôi vàng ạ!
Không được thày ạ !Nhà em gửi file để thày các thày xem giúp .Bạn thay chữ ActiveSheet.Pictures bằng ActiveSheet.Shapes
Không được thày ạ !Nhà em gửi file để thày các thày xem giúp .
Vừa định nói như thế thì Thầy đã post bài lên rồi! Xóa 5 hình chồng lên là được!Bạn có để ý thấy trong file của bạn tuy nhìn thấy 5 hình nhưng thực chất là 10 hình không?
Tức là: 5 hình nằm dưới 5 hình
Kiểm tra lại xem
(như vậy làm sao mà code chạy được: Vì 2 hình trùng tên)
Sub ShpResize()
[COLOR=#ff0000][B] Dim pic As Shape[/B][/COLOR]
Dim bMark As Boolean
[B][COLOR=#ff0000] Set pic = ActiveSheet.Shapes(Application.Caller)[/COLOR][/B]
[COLOR=#ff0000][B] With pic[/B][/COLOR]
bMark = (Len(.AlternativeText) > 0)
If bMark = False Then
.ScaleWidth 5, msoFalse, msoScaleFromMiddle
.ScaleHeight 5, msoFalse, msoScaleFromMiddle
.AlternativeText = "TRUE"
.ZOrder msoBringToFront
Else
.Left = Range(.Name).Left: .Top = Range(.Name).Top
.Width = Range(.Name).Width: .Height = Range(.Name).Height
[COLOR=#ff0000][B] .AlternativeText = ""[/B][/COLOR]
End If
End With
End Sub
Vừa định nói như thế thì Thầy đã post bài lên rồi! Xóa 5 hình chồng lên là được!
Nhà em đã kiểm tra lại đúng là 10 hình nhưng do lúc đầu load ảnh từ Folder nó nhỏ quá, nhà em nghĩ nó xóa ảnh cũ nạp ảnh mới, nên cư thế gọi sub . Nhưng nó cứ thế nạp ảnh mới nên thành 10 ảnh . Nhưng kiểm tra và chạy lại vẫn lỗi trên thày ạ . Hay còn chức năng nào cần phải kích hoạt không nhỉ ? Nhà em gửi tiếp File đính kèm tiếp, thật phiền các thày quá .Bạn có để ý thấy trong file của bạn tuy nhìn thấy 5 hình nhưng thực chất là 10 hình không?
Tức là: 5 hình nằm dưới 5 hình
Kiểm tra lại xem
(như vậy làm sao mà code chạy được: Vì 2 hình trùng tên)
Cám ơn sự nhiệt tình của các thày, nhà em sợ các thày chờ nên hơi vội , chậm tý nữa thì không phải post bài nữa . Code của thày Nghĩa chạy rồi ạ . Nhờ thày NDU xóa hộ bài trên với chức năng smod ạ . Nhanh nhảu đoảng quá ! cám ơn các thày . Còn vụ trùng hình chắc do gọi code 2 lần, Nhưng đáng ra nó phải xóa thì mới đúng .Nhưng với Excel 2003 cũng bị lỗi! Bạn sửa lại code như sau:
Mã:Sub ShpResize() [COLOR=#ff0000][B] Dim pic As Shape[/B][/COLOR] Dim bMark As Boolean [B][COLOR=#ff0000] Set pic = ActiveSheet.Shapes(Application.Caller)[/COLOR][/B] [COLOR=#ff0000][B] With pic[/B][/COLOR] bMark = (Len(.AlternativeText) > 0) If bMark = False Then .ScaleWidth 5, msoFalse, msoScaleFromMiddle .ScaleHeight 5, msoFalse, msoScaleFromMiddle .AlternativeText = "TRUE" .ZOrder msoBringToFront Else .Left = Range(.Name).Left: .Top = Range(.Name).Top .Width = Range(.Name).Width: .Height = Range(.Name).Height [COLOR=#ff0000][B] .AlternativeText = ""[/B][/COLOR] End If End With End Sub
Rồi, bây giờ bạn có thể click 1 lần cho nó bự ra, rồi click một lần nữa nó thu lại!
Cám ơn sự nhiệt tình của các thày, nhà em sợ các thày chờ nên hơi vội , chậm tý nữa thì không phải post bài nữa . Code của thày Nghĩa chạy rồi ạ . Nhờ thày NDU xóa hộ bài trên với chức năng smod ạ . Nhanh nhảu đoảng quá ! cám ơn các thày . Còn vụ trùng hình chắc do gọi code 2 lần, Nhưng đáng ra nó phải xóa thì mới đúng .
Cám ơn thày ! Không được rồi thày ơi! 5 cái ảnh cũ thì được nhưng nạp ảnh mới nó lại lỗi vậy .
Target.Parent.Pictures(Target.Address).Delete
ActiveSheet.Shapes(Target.Address).Delete
Tại Sub InsertPic, bạn thay câu lệnh này:
Mã:Target.Parent.Pictures(Target.Address).Delete
Thành câu lệnh này thử xem sao!
Mã:ActiveSheet.Shapes(Target.Address).Delete
Target.Parent với ActiveSheet là mấy thứ trời?
Nhưng quan trọng là Excel 2003 nó chịu với Shapes mà nó không chịu với Pictures mới đau!
Nói thật nha: Cái này TÔI KHÔNG TIN!
Cám ơn thày, nhà em có đĩa office 2003 nhưng dung lượng riêng nó đến 400 Mb nên không biết có cách gì để gửi không ạ ?Ngoài lề 1 chút: Không biết bạn nào có bộ Office 2003 Portable có thể chạy được trên Win7 và dùng được VBA không? Nếu có cho tôi xin link với
Bảo đảm có bộ office 2003, tôi test code 1 phát là biết liền lỗi ở đâu ngay
Em kiểm tra kỹ rồi, ai không tin thì cứ thử thôi. Excel 2007 trở về sau mới sử dụng được với nó!
!
Cám ơn thày, nhà em đã text thử, không thây nó báo lỗi nhưng chậm hơn và list để đổi ảnh tại cột B lại không còn. không biết sao nữa , làm các thày vất vả , nhà em ngại quá .Tại Sub InsertPic, bạn thay câu lệnh này:
Mã:Target.Parent.Pictures(Target.Address).Delete
Thành câu lệnh này thử xem sao!
Mã:ActiveSheet.Shapes(Target.Address).Delete
VÔ LÝ!
Thế chẳng lẽ Excel 2003 ta không Insert được Picture?
Vậy thì dòng code ActiveSheet.Pictures.Insert(FileName) chẳng đã dùng từ đởi office nào rồi sao?
Đó không phải là Picture và Pictures object thì gọi là gì?
không biết sao nữa , làm các thày vất vả , nhà em ngại quá .
Thầy qua Cơ quan em! Office 2000 cũng còn nhiều lắm ạ! Win 98, Win Me vẫn còn vài máy nữa đó! Nhà nước tiết kiệm muôn năm mà!Mình đành.. bó tay rồi
Tìm khắp cty cũng chẳng có máy nào còn xài Office 2003. Lượm được 1 bộ Potable Office 2003, mừng quá test 1 phát thì... ôi thôi, nó chẳng hổ trợ VBA
Thời buổi này còn xài Office 2003 rõ khổ (vì sẽ nhận được ít sự trợ giúp)
Cám ơn thày ! Nói như thày Nghĩa đúng đấy ạ . Các cơ quan xí nghiệp còn nhiều nơi và nhiều người còn đang dùng Win xp và office 2003 và được coi là "cơ bản", Win 7, Win 8 và office 2010 , 2013 là "vẽ vời" . Vì đa số còn đang dùng nên người ta không thấy bị lạc hậu . Nói thày đừng cười, có lúc gửi dữ liệu , họ nhận được gọi điện lại " Dữ liệu kiểu gì vậy, xem được quái đâu? gửi lại đi, không biết làm Excel à ?" . Vậy đó thày . Nhưng họ là A nên chịu , thì ghi sang đuôi .xls rồi gửi đi , gọi điện hỏi lại , họ bảo "lần sau cứ thế mà làm , bực cả minh !" .Đặc biệt dữ liệu có hỗ trợ VBA có khi còn không được chấp nhận vì họ không kiểm tra được Kết quả, công thức tính thế nào ( từ đâu đến đâu, bằng cái gì + - * / với cái gì ). Cũng có người , sau khi được hướng dẫn, dùng thử thú nhận : Hay đấy ! nhưng vẫn phải làm lại vì có phải mình tớ xem đâu . Thế đấy thày ạ !Mình đành.. bó tay rồi
Tìm khắp cty cũng chẳng có máy nào còn xài Office 2003. Lượm được 1 bộ Potable Office 2003, mừng quá test 1 phát thì... ôi thôi, nó chẳng hổ trợ VBA
Thời buổi này còn xài Office 2003 rõ khổ (vì sẽ nhận được ít sự trợ giúp)
Thầy qua Cơ quan em! Office 2000 cũng còn nhiều lắm ạ! Win 98, Win Me vẫn còn vài máy nữa đó! Nhà nước tiết kiệm muôn năm mà!
Cám ơn thày ! Nói như thày Nghĩa đúng đấy ạ . Các cơ quan xí nghiệp còn nhiều nơi và nhiều người còn đang dùng Win xp và office 2003 và được coi là "cơ bản", Win 7, Win 8 và office 2010 , 2013 là "vẽ vời" . Vì đa số còn đang dùng nên người ta không thấy bị lạc hậu
Nếu là một đối tác nước ngoài gửi cho file XLSX, XLSM, thậm chí là có code VBA bên trong thì chắc họ (hoặc sếp của họ) đã không nói vậy rồi.Nói thày đừng cười, có lúc gửi dữ liệu , họ nhận được gọi điện lại " Dữ liệu kiểu gì vậy, xem được quái đâu? gửi lại đi, không biết làm Excel à ?" . Vậy đó thày . Nhưng họ là A nên chịu , thì ghi sang đuôi .xls rồi gửi đi , gọi điện hỏi lại , họ bảo "lần sau cứ thế mà làm , bực cả minh !"
Họ gọi người thuê thôi ! và đặc biệt là họ thấy thế là bình thường . chẳng khác gì tài liệu tiếng nước ngoài: thuê dịch, thế là xong . Không làm được thì thuê ! thật là đơn giản . Do thày làm với người nước ngoài nhiều nên thấy "chướng" chứ nhiều người cả đời không quan hệ với đối tác là người nước ngoài, trừ khi dùng tiền "chùa" đi du lịch thì đã có phiên dịch thì họ lo gì . OK mà thày . Cái đáng sợ là họ thấy đó là điều tất nhiên !Xài cái gì là tùy theo sở thích và quan điểm của cá nhân hoặc tổ chức
Có điều các bạn cũng thấy trên mạng giờ người ta xài đến Office 2013 (thậm chí là 64bit). Mình còn "lẹt đẹt" tận đâu thì... có trục trặc gì tự mò vậy
Nếu là một đối tác nước ngoài gửi cho file XLSX, XLSM, thậm chí là có code VBA bên trong thì chắc họ (hoặc sếp của họ) đã không nói vậy rồi.
Lúc đó họ (hoặc sếp họ) phải làm sao nhỉ? Suy nghĩ xem!
Họ gọi người thuê thôi ! và đặc biệt là họ thấy thế là bình thường . chẳng khác gì tài liệu tiếng nước ngoài: thuê dịch, thế là xong . Không làm được thì thuê ! thật là đơn giản . Do thày làm với người nước ngoài nhiều nên thấy "chướng" chứ nhiều người cả đời không quan hệ với đối tác là người nước ngoài, trừ khi dùng tiền "chùa" đi du lịch thì đã có phiên dịch thì họ lo gì . OK mà thày . Cái đáng sợ là họ thấy đó là điều tất nhiên !
Vâng , cám ơn thày ! Nhà em cũng vậy, cái gì bây giờ chưa làm được thì sau này có điều kiện lại làm . Có việc mấy năm sau tự nhiên sực nhớ đến, khi làm được rồi , lắm lúc ngồi cười một mình . Thực ra cái này Thày Nghĩa tìm ra cái lỗi cơ bản rồi , chắc chạy trên Excel 2003 nên nó hơi chậm, Có khi nhà em tả có thể thày cũng biết nó lỗi cái gì : Tức là có lúc nếu nó xóa được ảnh khi ta kích vào sau khi phóng to, thi nó chạy tiếp bình thường . Còn không nó phóng to liên tiếp các ảnh khác khi ta kích vào và không thu nhỏ được nữa . Bây giờ sử lý được cái đó thì toàn bộ list và tên của ảnh nó không xuất hiện tại cột B nữa . Thực ra nhà em cũng muốn học các thày sử lý xem nó bị lỗi gì ? Ít ra ta cũng biết không phải lúc nào khi sử dụng Excel 2010 để ghi thành đuôi xls nó cũng chạy bình thường . Nếu lúc nào thày tìm ra lỗi,thày nhớ giúp nhà em với ! Hiện tại nhà em cứ làm trên Excel 2010 đã , khi có ai kêu nhà em tính sau . Xin cám ơn về sự uyên bác, xin cám ơn về sự tận tụy, xin cám ơn về sự nhiệt tình của thày .Tính mình rất hiếu kỳ. Mỗi khi gặp 1 vấn đề hơi "lạ lạ" là phải nhất định tìm hiểu tận gốc mới thôi
Trường hợp của bạn mình suy nghĩ mãi cũng không thấy có vấn đề gì. Ngoại trừ dòng lệnh LockAspectRatio = msoFalse không dùng được trên Excel 2003 thì các code còn lại là hoàn toàn tương thích
Tuy nhiên, để chắc ăn thì phải test trực tiếp... Cũng đã cố tìm máy nào đó có Office 2003 mà đành.. bó bột thôi
Ẹc... Ẹc... Tóm lại là: thua
(Để vài bữa hỏi thử xem ai có bộ Potable Office có hổ trợ VBA sẽ tính tiếp)
Vâng , cám ơn thày ! Nhà em cũng vậy, cái gì bây giờ chưa làm được thì sau này có điều kiện lại làm . Có việc mấy năm sau tự nhiên sực nhớ đến, khi làm được rồi , lắm lúc ngồi cười một mình . Thực ra cái này Thày Nghĩa tìm ra cái lỗi cơ bản rồi , chắc chạy trên Excel 2003 nên nó hơi chậm, Có khi nhà em tả có thể thày cũng biết nó lỗi cái gì : Tức là có lúc nếu nó xóa được ảnh khi ta kích vào sau khi phóng to, thi nó chạy tiếp bình thường . Còn không nó phóng to liên tiếp các ảnh khác khi ta kích vào và không thu nhỏ được nữa . Bây giờ sử lý được cái đó thì toàn bộ list và tên của ảnh nó không xuất hiện tại cột B nữa . Thực ra nhà em cũng muốn học các thày sử lý xem nó bị lỗi gì ? Ít ra ta cũng biết không phải lúc nào khi sử dụng Excel 2010 để ghi thành đuôi xls nó cũng chạy bình thường . Nếu lúc nào thày tìm ra lỗi,thày nhớ giúp nhà em với ! Hiện tại nhà em cứ làm trên Excel 2010 đã , khi có ai kêu nhà em tính sau . Xin cám ơn về sự uyên bác, xin cám ơn về sự tận tụy, xin cám ơn về sự nhiệt tình của thày .
InsertPic PicPath, Target, "ShpResize" <-- ([B][COLOR=#ff0000]A[/COLOR][/B])
Set Target = Range("A5").Offset(lR)
lR = lR + 1
Set Target = Range("A5").Offset(lR)
lR = lR + 1
InsertPic PicPath, Target, "ShpResize"
If bMark = False Then
.ScaleWidth 5, msoFalse, msoScaleFromMiddle
...
.AlternativeText = "TRUE"
Else
.AlternativeText = ""
End If
[COLOR=#ff0000]If bMark Then[/COLOR]
.ScaleWidth 5, msoFalse, msoScaleFromMiddle
...
[COLOR=#ff0000].AlternativeText = ""[/COLOR]
Else
[COLOR=#ff0000].AlternativeText = "TRUE"[/COLOR]
End If
Chổ này thì đúng. Em sơ sótTóm lại nếu trong folder có 1 ảnh thì không có ảnh nào được load. Nếu có n ảnh thì chỉ có (n - 1) ảnh được load. Để khắc phục thì đổi thành
Mã:Set Target = Range("A5").Offset(lR) lR = lR + 1 InsertPic PicPath, Target, "ShpResize"
Theo lôgic thì click lần đầu tiên vào ảnh thì ảnh phải phóng to vì ảnh hiện thời đang nhỏ. Nhưng với code hiện thời thì phải click lần thứ 2 thì ảnh mới to. Tức với mỗi ảnh ta tốn 1 click vô ích. Để khắc phục thì đổi code trong ShpResize
Mã:If bMark = False Then .ScaleWidth 5, msoFalse, msoScaleFromMiddle ... .AlternativeText = "TRUE" Else .AlternativeText = "" End If
thành
Mã:[COLOR=#ff0000]If bMark Then[/COLOR] .ScaleWidth 5, msoFalse, msoScaleFromMiddle ... [COLOR=#ff0000].AlternativeText = ""[/COLOR] Else [COLOR=#ff0000].AlternativeText = "TRUE"[/COLOR] End If
Sub ShpResize()
Dim pic As Picture
Dim bMark As Boolean
On Error Resume Next
Set pic = Sheet1.Pictures(Application.Caller)
With pic.ShapeRange
[COLOR=#ff0000]bMark = (Len(.AlternativeText) > 0)[/COLOR]
[COLOR=#ff0000]If bMark = False Then[/COLOR]
.ScaleWidth 3, msoFalse, msoScaleFromMiddle
.ScaleHeight 3, msoFalse, msoScaleFromMiddle
.AlternativeText = "TRUE"
.ZOrder msoBringToFront
Else
.Left = Range(.Name).Left: .Top = Range(.Name).Top
.Width = Range(.Name).Width: .Height = Range(.Name).Height
.AlternativeText = vbNullString
End If
End With
End Sub
Chổ này thì đúng. Em sơ sót
Nhưng chổ này
Thì em nghĩ là sai! Lúc đầu AlternativeText chưa có gì, mà bMark = (Len(.AlternativeText) > 0) nên bMark sẽ =FALSE
Vậy nên xét điều kiện khi bMark=FALSE mới phóng to ảnh là chính xác rồi còn gì
Nếu sửa như anh thì click vào chẳng có chuyện gì xãy ra cả
Toàn bộ code của em viết là thế này:
Có khi anh đang nói đến code nào đó đã bị "độ" lại cũng không chừngMã:Sub ShpResize() Dim pic As Picture Dim bMark As Boolean On Error Resume Next Set pic = Sheet1.Pictures(Application.Caller) With pic.ShapeRange [COLOR=#ff0000]bMark = (Len(.AlternativeText) > 0)[/COLOR] [COLOR=#ff0000]If bMark = False Then[/COLOR] .ScaleWidth 3, msoFalse, msoScaleFromMiddle .ScaleHeight 3, msoFalse, msoScaleFromMiddle .AlternativeText = "TRUE" .ZOrder msoBringToFront Else .Left = Range(.Name).Left: .Top = Range(.Name).Top .Width = Range(.Name).Width: .Height = Range(.Name).Height .AlternativeText = vbNullString End If End With End Sub
Tôi viết rất rõ mà: "Trước hết góp ý về code trong bài #35 và #43"
Ở lần click đầu tiên thì .AlternativeText = "tên ảnh", tức bMark = TRUE
Anh xem kỹ lại đi: Cả code ở bài 35 và 43 đều không có cái vụ .AlternativeText = "tên ảnh" đâuỞ lần click đầu tiên thì .AlternativeText = "tên ảnh", tức bMark = TRUE
Sub ShpResize()
Dim pic As Picture
Dim bMark As Boolean
Set pic = Sheet1.Pictures(Application.Caller)
With pic.ShapeRange
[COLOR=#ff0000]bMark = (Len(.AlternativeText) > 0)
If bMark = False Then[/COLOR]
.ScaleWidth 5, msoFalse, msoScaleFromMiddle
.ScaleHeight 5, msoFalse, msoScaleFromMiddle
[COLOR=#ff0000] .AlternativeText = "TRUE"[/COLOR]
.ZOrder msoBringToFront
Else
.Left = Range(.Name).Left: .Top = Range(.Name).Top
.Width = Range(.Name).Width: .Height = Range(.Name).Height
[COLOR=#ff0000].AlternativeText = vbNullString[/COLOR]
End If
End With
End Sub
Sub ShpResize()
Dim pic As Shape
Dim bMark As Boolean
Set pic = ActiveSheet.Shapes(Application.Caller)
With pic
[COLOR=#ff0000] bMark = (Len(.AlternativeText) > 0)
If bMark = False Then[/COLOR]
.ScaleWidth 5, msoFalse, msoScaleFromMiddle
.ScaleHeight 5, msoFalse, msoScaleFromMiddle
[COLOR=#ff0000].AlternativeText = "TRUE"[/COLOR]
.ZOrder msoBringToFront
Else
.Left = Range(.Name).Left: .Top = Range(.Name).Top
.Width = Range(.Name).Width: .Height = Range(.Name).Height
[COLOR=#ff0000] .AlternativeText = ""[/COLOR]
End If
End With
End Sub
Tôi có nói code không êm xuôi đâu. Tôi chỉ nói "phí" 1 lần click đầu tiên sau khi load ảnh.TÁC GIÁ CODE LÀ EM đấy anh à!
Dù là bài 35 hay 36 hay số mấy thì code đó cũng là của em
---------------
Anh xem kỹ lại đi: Cả code ở bài 35 và 43 đều không có cái vụ .AlternativeText = "tên ảnh" đâu
Tất cả 2 code trong 2 bài ấy đều đặt điều kiện vầy: bMark = (Len(.AlternativeText) > 0)
Code bài 35:
Code bài 43:Mã:Sub ShpResize() Dim pic As Picture Dim bMark As Boolean Set pic = Sheet1.Pictures(Application.Caller) With pic.ShapeRange [COLOR=#ff0000]bMark = (Len(.AlternativeText) > 0) If bMark = False Then[/COLOR] .ScaleWidth 5, msoFalse, msoScaleFromMiddle .ScaleHeight 5, msoFalse, msoScaleFromMiddle [COLOR=#ff0000] .AlternativeText = "TRUE"[/COLOR] .ZOrder msoBringToFront Else .Left = Range(.Name).Left: .Top = Range(.Name).Top .Width = Range(.Name).Width: .Height = Range(.Name).Height [COLOR=#ff0000].AlternativeText = vbNullString[/COLOR] End If End With End Sub
Còn chuyện có tên ảnh trong AlternativeText thì đó cũng là sơ suất của người ta, chẳng ảnh hưởng gì đến code cả. Dù lần đầu click có trục trặc thì những lần sau vẫn êm xuôiMã:Sub ShpResize() Dim pic As Shape Dim bMark As Boolean Set pic = ActiveSheet.Shapes(Application.Caller) With pic [COLOR=#ff0000] bMark = (Len(.AlternativeText) > 0) If bMark = False Then[/COLOR] .ScaleWidth 5, msoFalse, msoScaleFromMiddle .ScaleHeight 5, msoFalse, msoScaleFromMiddle [COLOR=#ff0000].AlternativeText = "TRUE"[/COLOR] .ZOrder msoBringToFront Else .Left = Range(.Name).Left: .Top = Range(.Name).Top .Width = Range(.Name).Width: .Height = Range(.Name).Height [COLOR=#ff0000] .AlternativeText = ""[/COLOR] End If End With End Sub
Vậy nên phần code này không cần phải sửa gì cả
(File ở bài 35 bị lỗi là vì 1 chuyện hoàn toàn khác, đã xử lý xong)
Tôi có bàn về chuyện lỗi kia đâu???
Mà người góp ý thì cứ góp ý còn việc sửa hay không thì là chuyện của người khác. Chả ai bắt ai đâu mà
Anh góp ý thì em và mọi người đều cảm ơn (chuyện đương nhiên)
----------------------------------------------------
Ngoài lề một chút:
Em biết là anh đã xem qua topic này vài lần, chắc cũng định bỏ đi rồi nhưng vì thấy thằng em nó sai mà không ai phát hiện nên anh ngứa tay vào đây góp vài lời (em rất cảm ơn về điều này)
Em biết là anh ngại giao tiếp với em nên đã "nói tránh" đi là góp ý cho bài này, bài nọ (không phải bài của em)...
Ẹc... Ẹc... dù là bài nào trong topic này cũng có liên quan đến em thôi
Em khộng ngại mà nói thằng rằng: thời gian gần đây em cũng ngại giao tiếp với anh, vì anh hay nỗi nóng bất thường nên sau này em chẳng khi nào góp ý bất cứ vấn đề gì có liên đến code anh viết (anh thừa hiểu lý do vì sao)
Thôi thì đã lỡ vào đây rồi, có góp ý anh cứ góp ý thẳng (không cần phải "nói tránh" đi đâu). Tính em phân biệt rõ ràng lắm, dù có ghét ai đến mấy nhưng vẫn chịu học hỏi nếu người đó có cái hay... huống chi em với anh dù có "tránh mặt" nhau cũng đâu phải thuộc dạng ghét cay ghét đăng hay thù hằn gì
Anh nghĩ em nói đúng không?
----------------------------------------------------
Ôi... mông lung quá!![]()
Vâng! Có sai chứ anh! Đó là trường hợp anh nói về AlternativeTextK
Góp ý? Sẵn sàng, nhưng cứ nói thẳng. Đừng quanh co, bịa tình huống.
Tôi góp ý có cái gì sai không? Nếu sai thì nói ra để tôi rút kinh nghiệm. Còn nếu đúng thì tại sao lại có chuyện "kể" ra những chuyện như trên?
Hình như anh chưa hiểu ý em thì phải (cũng như bao lần trước)Tôi sẽ không viết thêm gì nữa.
-----------------
Tôi đã nói là không viết thêm nữa tức sẽ không có chuyện tranh luận gì ở đây. Vậy đề nghị BQT để nguyên bài này của tôi. Một ý kiến, vài lời giải thích nhưng của người có văn hóa mà. Chuyện nói thẳng vì là toàn là đàn ông mà lại đàn ông có tuổi mà.
Các thày cũng cho nhà em nói thẳng là "một nửa" của ta đáng yêu, đáng quý biết bao nhiêu mà nhiều khi vẫn phải "Quay mặt làm ngơ" mà . Với hai thày vừa là "cao thủ" của GPE cả về kiến thức, cả về tuổi đời và cả về đối nhân sử thế ; Máy móc là "kẻ" vô tri mà còn xung đột mà . Theo nhà em thì " Không có giải nhất" là phương án tối ưu , Mong các thày đừng cho rằng nhà em " nói leo " .
Public aFiles, sFolder As String
Sub ShpResize()
Dim shp As Shape, rngPos As Range
Dim bMark As Boolean
On Error Resume Next
Set shp = ActiveSheet.Shapes(Application.Caller)
With shp
Set rngPos = Range(.Name)
bMark = (Len(.AlternativeText) > 0)
If bMark = False Then
.ScaleWidth 3, msoFalse, msoScaleFromMiddle
.ScaleHeight 3, msoFalse, msoScaleFromMiddle
.AlternativeText = "TRUE"
.ZOrder msoBringToFront
Else
.Left = rngPos.Left: .Top = rngPos.Top
.Width = rngPos.Width: .Height = rngPos.Height
.AlternativeText = ""
End If
End With
End Sub
Sub ShpReset()
Dim shp As Shape, bMark As Boolean, rngPos As Range
On Error Resume Next
For Each shp In ActiveSheet.Shapes
With shp
If .Name Like "$*$*" Then
bMark = (Len(.AlternativeText) > 0)
Set rngPos = Range(.Name)
.Left = rngPos.Left: .Top = rngPos.Top
.Width = rngPos.Width: .Height = rngPos.Height
If bMark Then .AlternativeText = vbNullString
End If
End With
Next
End Sub
Sub SelectFolder()
Dim arr, vFolder, pic
Dim Target As Range, shp As Shape
Dim lR As Long
Dim PicPath As String
On Error Resume Next
vFolder = CreateObject("Shell.Application").BrowseForFolder(0, "", 1).Self.Path
If TypeName(vFolder) = "String" Then
If Right(vFolder, 1) <> "\" Then vFolder = vFolder & "\"
arr = FilesFoldersList(vFolder, True, "*.jpg", False)
If IsArray(arr) Then
aFiles = arr
sFolder = CStr(vFolder)
Range("F1") = sFolder
For Each pic In arr
PicPath = sFolder & CStr(pic)
Set Target = Range("A5").Offset(lR)
lR = lR + 1
Set shp = InsertPic(PicPath, Target, "ShpResize")
Next
Range("F1").Select
End If
End If
End Sub
Function InsertPic(ByVal PicPath As String, ByVal Target As Range, Optional ByVal Action As String = "") As Shape
Dim shp As Shape
On Error Resume Next
With Target
.Parent.Shapes(Target.Address).Delete
Set shp = .Parent.Shapes.AddPicture(PicPath, True, True, .Left, .Top, .Width, .Height)
End With
If Not shp Is Nothing Then
shp.Name = Target.Address
shp.AlternativeText = ""
If Val(Application.Version) > 11 Then shp.LockAspectRatio = msoFalse
shp.OnAction = Action
Set InsertPic = shp
End If
End Function
Đó là vì ngoài code trong Module còn có code sự kiện Change, SelectionChange (nằm trong Sheet). Bạn copy ra file khác nhưng quên không mang theo mấy code này nên phần Validation list không hoạt động. Chú ý nha!Bây giờ sử lý được cái đó thì toàn bộ list và tên của ảnh nó không xuất hiện tại cột B nữa
Khi bạn điều chỉnh kích thước cell xong, chỉ cần click chuột vào 1 cell nào đó là ảnh tự cân chỉnh thôi mà. Tính năng này được thực hiện từ sự kiện SelectionChange:Cám ơn thày ! Code chạy tốt trên Excel 2003 rồi ạ . Song có điều thày giúp nhà em thêm chút nữa là : Tất cả tính năng như File cũ ( Khi điều chỉnh cell ảnh tự động điều chỉnh theo - điều này để điều chỉnh sự cân đối của ảnh )
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
On Error Resume Next
[B][COLOR=#ff0000]ShpReset[/COLOR][/B]
If Not Intersect(Range("B5:B30"), Target) Is Nothing Then
If Target.Count = 1 Then
If IsArray(aFiles) Then
With Target.Validation
.Delete
.Add 3, , , Join(aFiles, ",")
End With
End If
End If
End If
End Sub
Dù phóng to theo tỷ lệ nào thì khi thu nhỏ ảnh cũng về kích thước ban đầu ( Hiện tại ảnh được thu về theo tỷ lệ , nên có lúc nó thu về kích thước nhỏ hơn cell hiện tại, vả lại kích thước ảnh không phải lúc nào cũng giống nhau nên nhà em phải điều chỉnh chiều rộng và chiều dài khác nhau để cân đối ảnh nên khi thu nhỏ rất cần nó trở lại kích thước ban đầu .
!
Sub ShpResize()
Dim shp As Shape, rngPos As Range
Dim bMark As Boolean
On Error Resume Next
Set shp = ActiveSheet.Shapes(Application.Caller)
With shp
Set rngPos = Range(.Name)
bMark = (Len(.AlternativeText) > 0)
If bMark = False Then
.ScaleWidth 3, msoFalse, msoScaleFromMiddle
.ScaleHeight 3, msoFalse, msoScaleFromMiddle
.AlternativeText = "TRUE"
.ZOrder msoBringToFront
Else
[COLOR=#ff0000].Left = rngPos.Left: .Top = rngPos.Top
.Width = rngPos.Width: .Height = rngPos.Height[/COLOR]
.AlternativeText = ""
End If
End With
End Sub
Thưa thày, khi đã load ảnh điều chỉnh cell ảnh không điều chỉnh theo đâu ạ . chỉ khi đổi ảnh nó mới điều chỉnh theo kích thước mới thày ạ .
Cám ơn thày Nhà em gưi file để thày kiểm tra giúp ạ .Bạn đưa file của bạn lên đây xem thử! Tôi test không phát hiện có gì bất thường cả (kích thước ảnh được điều chỉnh ngon lành cho cả 2 trường hợp load ảnh mới và thay đổi ảnh theo validation)
Cám ơn thày Nhà em gưi file để thày kiểm tra giúp ạ .
Function InsertPic(ByVal PicPath As String, ByVal Target As Range, Optional ByVal Action As String = "") As Shape
Dim shp As Shape
On Error Resume Next
With Target
.Parent.Shapes(Target.Address).Delete
Set shp = .Parent.Shapes.AddPicture(PicPath, True, True, .Left, .Top, .Width, .Height)
End With
If Not shp Is Nothing Then
shp.Name = Target.Address
shp.AlternativeText = ""
[COLOR=#ff0000] If Val(Application.Version) > 11 Then shp.LockAspectRatio = msoFalse[/COLOR]
shp.OnAction = Action
End If
End Function
[COLOR=#ff0000] shp.LockAspectRatio = msoFalse[/COLOR]
Đúng rồi thày ạ, còn cho hiện tên cùng với ảnh tại list khi load ảnh ngay lần đầu thì sửa code thế nào ạ ?
Sub SelectFolder()
Dim arr, vFolder, pic
Dim Target As Range, shp As Shape
Dim lR As Long
Dim PicPath As String
On Error Resume Next
vFolder = CreateObject("Shell.Application").BrowseForFolder(0, "", 1).Self.Path
If TypeName(vFolder) = "String" Then
If Right(vFolder, 1) <> "\" Then vFolder = vFolder & "\"
arr = FilesFoldersList(vFolder, True, "*.jpg", False)
If IsArray(arr) Then
aFiles = arr
sFolder = CStr(vFolder)
Range("F1") = sFolder
For Each pic In arr
PicPath = sFolder & CStr(pic)
Set Target = Range("A5").Offset(lR)
lR = lR + 1
Set shp = InsertPic(PicPath, Target, "ShpResize")
[COLOR=#ff0000]Target.Offset(, 1) = CStr(pic)[/COLOR]
Next
Range("F1").Select
End If
End If
End Sub
Thày NDU cho nhà em hỏi thêm chút là : nếu lần sau số lượng ảnh nhiều hơn lần trước thì không vấn đề gì . Nhưng nếu ít hơn thì số ảnh thừa vẫn tồn tại nên phải xóa thủ công . Nhà em đã định tự giải quyết bằng cách viết thêm dòng lệnh để xóa luôn 2 cột (A:B) rồi chèn lại 2 cột đó nhưng có vẻ không hay lắm mà dò để sửa code thì sợ code "độ" không đồng bộ . Mong thày chỉ giáo,Tức là xóa ảnh cũ trước khi load ảnh mới .
Sub Test()
ActiveSheet.Pictures.Delete
End Sub
Cám ơn thày, nhà em sợ thày bận nên mày mò . Vâng nhà em sẽ thử và thông báo ạ !Cái đó tôi có thấy nhưng chưa tiến hành là vì liên quan đến cái vụ 2003 của bạn đấy!
Bây giờ bạn vui lòng thí nghiệm giùm tôi thế này nhé:
- Mở 1 file Excel trắng
- Chèn 1 vài hình (chèn bằng tay)
- Xong bạn chạy code này thử:
- Kết quả thế nào, báo tôi biết rồi ta tính tiếpMã:Sub Test() ActiveSheet.Pictures.Delete End Sub
Lưu ý: thí nghiệm trên phải được thực hiện trên Excel 2003 nhé
Sub chạy tốt thày ạ ! Nhà em hiểu ý thày rồi : cho dòng lệnh trên vào sub SelectFolder Ngay dưới dòng lệnh On Error Resume Next và chạy tốt rồi thày ạ, tức là trước khi lấy ảnh mới thì xóa toàn bộ ảnh cũ . Thấy thày chạy giúp mọi người khắp diễn đàn nhà em thấy ngại thật sự ! Xin Cám ơn thày, người thày tận tụy !Cái đó tôi có thấy nhưng chưa tiến hành là vì liên quan đến cái vụ 2003 của bạn đấy!
Bây giờ bạn vui lòng thí nghiệm giùm tôi thế này nhé:
- Mở 1 file Excel trắng
- Chèn 1 vài hình (chèn bằng tay)
- Xong bạn chạy code này thử:
- Kết quả thế nào, báo tôi biết rồi ta tính tiếpMã:Sub Test() ActiveSheet.Pictures.Delete End Sub
Lưu ý: thí nghiệm trên phải được thực hiện trên Excel 2003 nhé
Ai bảo bạn làm thế nhỉ? Không bao giờ Thầy NDU "trảm" Object mà không có tên tuổi! Bạn mà dùng câu lệnh đó thì vô hình chung nó xóa tất cả các hình trên sheet thì khổ đấy! Trừ khi bạn muốn là thế!Sub chạy tốt thày ạ ! Nhà em hiểu ý thày rồi : cho dòng lệnh trên vào sub SelectFolder Ngay dưới dòng lệnh On Error Resume Next và chạy tốt rồi thày ạ . Cám ơn thày !
Đúng rồi đó thầy ! Vì sau đó ta nạp ảnh mới toàn bộ mà , còn nếu muồn thay một vài ảnh thì thay bằng list chứ không chạy sub nữa . Kể thày nhắc cũng nguy hiểm , nhỡ ai đó "bấm chơi" một cài thì tèo ( nếu vậy thì bỏ nút bấm và chạy bằng lệnh tắt, nếu ai không biết lệnh thì không chạy được ) , Nghe có vẻ không ổn lắm . Nhưng thực nhà em thấy phiền các thày nhiều nên cố tự lực chút ! cám ơn thày chỉ dẫn .Ai bảo bạn làm thế nhỉ? Không bao giờ Thầy NDU "trảm" Object mà không có tên tuổi! Bạn mà dùng câu lệnh đó thì vô hình chung nó xóa tất cả các hình trên sheet thì khổ đấy! Trừ khi bạn muốn là thế!
Nếu bạn muốn xóa tất cả thì tôi cũng có một cái thủ tục cho bạn, nó xóa tất Picture, kể cả những Shape!Đúng rồi đó thầy ! Vì sau đó ta nạp ảnh mới toàn bộ mà , cám ơn thày chỉ dẫn .
Thực ra Thày nhắc mới nhớ, nói chung có vẻ không an toàn . Yêu cầu là xóa toàn bộ ảnh đã nạp vào cột B thày ạ , vậy dòng lệnh viết thế nào ạ ?Nếu bạn muốn xóa tất cả thì tôi cũng có một cái thủ tục cho bạn, nó xóa tất Picture, kể cả những Shape!
ActiveSheet.DrawingObjects.Delete
Tuy nhiên, tôi không khuyến khích bạn dùng thủ tục này, bởi một lúc nào đó ta giữ vài hình ảnh lại, LOGO cty chẳng hạn, đã là một chương trình gì đó, bạn không muốn để một vài hình ảnh về bạn sao nhỉ?
Chỉ có thể là dùng vòng lặp thôi! Đặt tên hình cũng rất quan trọng, nếu đặt tên theo địa chỉ ô như Thầy NDU làm thì rất dễ quản lý, muốn xóa cũng rất thuận tiện!Thực ra Thày nhắc mới nhớ, nói chung có vẻ không an toàn . Yêu cầu là xóa toàn bộ ảnh đã nạp vào cột B thày ạ , vậy dòng lệnh viết thế nào ạ ?
Sub XoaHinh()
ActiveSheet.Shapes.Range(Array([COLOR=#0000ff]"Picture 1", "Picture 2", "Picture 3"[/COLOR])).Delete
End Sub
Bây giờ nhà em chỉ cần xóa hết ảnh từ B5 trở đi để nạp ảnh mới . Vì dòng lệnh trên xóa hết ảnh trên sheet nên không an toàn . Hay nhất là sửa được câu lệnh xóa ảnh cũ nạp ảnh mới Thành xóa toàn bộ ảnh cũ trước khi nạp ảnh mới thày ạ, nhưng nhà em không biết sửa thế nào vì code liên quan đến tất cả các sub nên nhà em không dám mạo hỉểm .Chỉ có thể là dùng vòng lặp thôi! Đặt tên hình cũng rất quan trọng, nếu đặt tên theo địa chỉ ô như Thầy NDU làm thì rất dễ quản lý, muốn xóa cũng rất thuận tiện!
Chắc chắn là được, thày ạ . Nhưng tên ảnh không đổi được, từ hôm qua đến giờ thày NDU đã giúp và sử dụng tốt rồi ạ ( tức là nạp ảnh và cà tên theo thư mục ảnh ). Giờ chỉ cần xóa ảnh cũ vì nếu lần nạp sau ít ảnh hơn lần trước đó thì còn một số ảnh trước đó vẫn tồn tại ngoài yêu cầu mà thày . cần xóa số ảnh thừa này ạ.Không biết trên Excel 2003 bạn có thể xóa hình bằng cách này không nhỉ:
Mã:Sub XoaHinh() ActiveSheet.Shapes.Range(Array([COLOR=#0000ff]"Picture 1", "Picture 2", "Picture 3"[/COLOR])).Delete End Sub
Bạn thử insert các picture và đặt tên lần lượt như các tên có màu xanh rồi cho chạy thủ tục đó xem nó có dùng được không, hiện tại tôi đang dùng Excel 2010 nên không test được!
Haha, bạn có biết khi tôi vọc code, tôi đã lưu lại nhiều file không? Hoặc giả tôi vọc tùm lum nhưng khi thoát tôi không lưu lại hoặc save as thành file mới không? Bạn cứ vọc thoải mái sợ quái gì code chứ!Bây giờ nhà em chỉ cần xóa hết ảnh từ B5 trở đi để nạp ảnh mới . Vì dòng lệnh trên xóa hết ảnh trên sheet nên không an toàn . Hay nhất là sửa được câu lệnh xóa ảnh cũ nạp ảnh mới Thành xóa toàn bộ ảnh cũ trước khi nạp ảnh mới thày ạ, nhưng nhà em không biết sửa thế nào vì code liên quan đến tất cả các sub nên nhà em không dám mạo hỉểm .
"Vọc" code thì nhà em "vọc" nhiều rồi, nhưng với code down trên diễn đàn về vì thấy hay hoặc gần đúng với yêu cầu của mình thì sửa theo ý mình, nếu không được thì bỏ . Nhưng đây là công sức của các thày bỏ ra để giúp cụ thể theo yêu cầu file của mình vả lại trình độ các thày cao hơn nhà em rất nhiều nên sửa kiểu gì cũng "lợn lành thành lợn què thôi ", bởi xem code phần lớn còn chưa hiểu , sao dám sửa ạ ! Nhưng thày khuyến khích " Sợ quái gì nó " nên nhà em coppy sang một tập rồi "Vọc đại đi ", cuối cùng thì có vẻ nó "nể" mình nên chạy . Lúc đầu do cứ tìm cách chọn ảnh để xóa nên thất bại (nó yêu cầu phải chọn từng ảnh theo từng cell theo địa chỉ tuyệt đối hoặc đích danh tên ảnh , nó mới xóa ). Cuối cùng nhà em thêm 2 câu lệnh sau vào ngay đầu code để nó xóa ảnh cũ trước khi load ảnh mới :Haha, bạn có biết khi tôi vọc code, tôi đã lưu lại nhiều file không? Hoặc giả tôi vọc tùm lum nhưng khi thoát tôi không lưu lại hoặc save as thành file mới không? Bạn cứ vọc thoải mái sợ quái gì code chứ!
Kể thày nhắc cũng nguy hiểm , nhỡ ai đó "bấm chơi" một cài thì tèo ( nếu vậy thì bỏ nút bấm và chạy bằng lệnh tắt, nếu ai không biết lệnh thì không chạy được ) , Nghe có vẻ không ổn lắm . Nhưng thực nhà em thấy phiền các thày nhiều nên cố tự lực chút ! cám ơn thày chỉ dẫn .
Sub SelectFolder()
Dim arr, vFolder, pic
Dim Target As Range, shp As Shape
Dim lR As Long
Dim PicPath As String
On Error Resume Next
vFolder = CreateObject("Shell.Application").BrowseForFolder(0, "", 1).Self.Path
If TypeName(vFolder) = "String" Then
If Right(vFolder, 1) <> "\" Then vFolder = vFolder & "\"
arr = FilesFoldersList(vFolder, True, "*.jpg", False)
If IsArray(arr) Then
[COLOR=#ff0000]ActiveSheet.Pictures.Delete[/COLOR]
aFiles = arr
sFolder = CStr(vFolder)
Range("F1") = sFolder
For Each pic In arr
PicPath = sFolder & CStr(pic)
Set Target = Range("A5").Offset(lR)
lR = lR + 1
Set shp = InsertPic(PicPath, Target, "ShpResize")
Target.Offset(, 1).Value = CStr(pic)
Next
Range("F1").Select
End If
End If
End Sub
Range("B5:B1000").ClearContents
Thay vì Select, rồi lại Selection.ClearContents. Bạn có thể gộp lại thành:Cuối cùng nhà em thêm 2 câu lệnh sau vào ngay đầu code để nó xóa ảnh cũ trước khi load ảnh mới :
Range([A5], [B5].End(xlDown).Resize(, 1)).Select
Selection.ClearContents
Té ra không phải ảnh load vào comment mà là trên cell và do tên tại cột B sinh ra , (cột A chỉ là cái khung chứa ảnh) nên nó nghe, trước đó cứ chọn cột A để xóa nên không đựợc . Cám ơn các thày đã giúp đỡ và chỉ dẫn .
Úi dà ! Nhà em vừa gửi bài xong quay lại thấy bài của thày. May quá, đúng ý của thày luôn, thày cho nhà em "cắp tráp " theo hầu , được không ạ ? Tiếc thật, nếu ở gần , dứt khoát nhà em đến thăm hầu chuyện thầy một hôm .Xin cám ơn thày !Chẳng sao cả!
Nếu bạn chắc rằng trên bảng tính không có bất cứ HÌNH nào "ngoài luồng" thì chơi được. Ở đây tôi nhắc đến từ HÌNH có nghĩa là Picture, các object khác (như hình vẽ, button...) không được tính
Vậy code thế này:
Sẽ không lo bấm bậyMã:Sub SelectFolder() Dim arr, vFolder, pic Dim Target As Range, shp As Shape Dim lR As Long Dim PicPath As String On Error Resume Next vFolder = CreateObject("Shell.Application").BrowseForFolder(0, "", 1).Self.Path If TypeName(vFolder) = "String" Then If Right(vFolder, 1) <> "\" Then vFolder = vFolder & "\" arr = FilesFoldersList(vFolder, True, "*.jpg", False) If IsArray(arr) Then [COLOR=#ff0000]ActiveSheet.Pictures.Delete[/COLOR] aFiles = arr sFolder = CStr(vFolder) Range("F1") = sFolder For Each pic In arr PicPath = sFolder & CStr(pic) Set Target = Range("A5").Offset(lR) lR = lR + 1 Set shp = InsertPic(PicPath, Target, "ShpResize") Target.Offset(, 1).Value = CStr(pic) Next Range("F1").Select End If End If End Sub
--------------
Trường hợp khác: trên sheet, ngoài hình chèn bằng code còn có những hình khác được chèn bằng tay. Để xóa những hình trước đó đã nạp (tại cột A) thì thay đoạn màu đỏ ở trên bằng code:
Mã:Range("B5:B1000").ClearContents