Tạo popup khi kích vào một ô

Liên hệ QC

cauthungoaihang

Thành viên mới
Tham gia
18/4/09
Bài viết
6
Được thích
1
Em đang muốn làm một sheet tổng, ở sheet này khi kích vào mộ ô nào đó sẽ hiện lên một cái bảng, mà cái bảng này đang ở sheet bên kia. (Ý em là hiện lên như một cái popup, chứ không phải là Hyperlink sang sheet bên kia).

Chi tiết em ghi trong file đính kèm, bác nào có cao kiến thì hướng dẫn em với, em cảm ơn nhiều.+-+-+-+
 

File đính kèm

Em đang muốn làm một sheet tổng, ở sheet này khi kích vào mộ ô nào đó sẽ hiện lên một cái bảng, mà cái bảng này đang ở sheet bên kia. (Ý em là hiện lên như một cái popup, chứ không phải là Hyperlink sang sheet bên kia).

Chi tiết em ghi trong file đính kèm, bác nào có cao kiến thì hướng dẫn em với, em cảm ơn nhiều.+-+-+-+

Đòi hỏi nghe chừng rất đơn giản mà làm được chắc cũng.. sặc máu
 
Có thể làm một cái form trong đó có nhúng một cái SheetSpread vào trong đó, ẩn hiện khi Selection, hic hic, căng quá!

Ý mình nói là là GIỐNG Y CHANG như cái giao diện mà tác giả yêu cầu ấy chứ (còn nếu là UserForm thì đâu nói làm gì)
Mặc khác: Nếu dùng SpreadSheet lại thêm vấn đề máy có control này mà máy lại không có ---> Thêm cái rắc rối nữa
 
to ndu:
mình cứ làm đại đi a, càng giống càng tốt --=0

to HTN:
bác là chuyên gia về Form mà, sao đành bó tay mấy vụ này :-=

to cauthungoaihang:
bạn mở file, chạy Macro và chọn vào các ô D4, D5 để xem kết quả.

'- - -
đã chỉnh lại form cho thật giống với đề bài :-=
no bar.png

Link: https://www.mediafire.com/?hqahee5x92dkhwi
 
Lần chỉnh sửa cuối:
Ý mình nói là là GIỐNG Y CHANG như cái giao diện mà tác giả yêu cầu ấy chứ (còn nếu là UserForm thì đâu nói làm gì)
Mặc khác: Nếu dùng SpreadSheet lại thêm vấn đề máy có control này mà máy lại không có ---> Thêm cái rắc rối nữa
Thực tế là ngay cả ListView của bài này:

to ndu:
mình cứ làm đại đi a, càng giống càng tốt --=0

to HTN:
bác là chuyên gia về Form mà, sao đành bó tay mấy vụ này :-=

to cauthungoaihang:
bạn mở file, chạy Macro và chọn vào các ô D4, D5 để xem kết quả.

Thì em cũng không xem được! Chỉ có xài ListView "chính chủ" do máy em "sản xuất" ra mà thôi! Chán thiệt đó.

to HTN:
bác là chuyên gia về Form mà, sao đành bó tay mấy vụ này :-=

Làm cái na ná thì OK, còn làm giống như thế thì e rằng y như lời Thầy NDU nói.

Với cái này thì Access làm việc một cách dễ dàng (kiểu Main Form, Sub Form).
 
Có thể làm một cái form trong đó có nhúng một cái SheetSpread vào trong đó, ẩn hiện khi Selection, hic hic, căng quá!
Bỏ qua cái vụ thanh cuộn kia thì em nghĩ đến một phương án cũng khá đơn giản: CopyPicture kết hợp với SelectionChange.
Code cho việc này có lẽ cũng không đến nỗi nào (nhưng mà em lười quá, với lại cũng đang bận, nên...)
 
Bỏ qua cái vụ thanh cuộn kia thì em nghĩ đến một phương án cũng khá đơn giản: CopyPicture kết hợp với SelectionChange.
Code cho việc này có lẽ cũng không đến nỗi nào (nhưng mà em lười quá, với lại cũng đang bận, nên...)
Ngay từ đầu anh đã nghĩ đến phương án này, nhưng lại tự hỏi liệu tác giả có tác động gì trên cái "popup" này vào sheet hay không nên không tính tới nó.
 
cho e hỏi nguyên nhân a và bác HTN ko mở được file trên, và cách khắc phục ntn được ko ah?

Tôi không nghiên cứu nên không phán nguyên nhân do đâu. Nhưng nếu bị gí dao vào cổ bắt đoán mò thì tôi sẽ phán: do nguyên nhân nào đó, rất có thể là do thư viện mà bạn dùng (Microsoft Windows Common Controls MSCOMCTL.OCX) có phiên bản khác với phiên bản có trên máy tôi.

Bất luận nguyên nhân là gì nếu tôi đã nhận được của đối tác, ở đây là bạn, thì tôi xử lý như sau. Khi tôi hiển thị Form trong VBA thì không có ListView. Tôi chọn Tools --> References --> bỏ chọn chỗ MISSING --> OK --> lưu lại file (save) --> chọn ListView trên Toolbox và đặt lên Form --> thiết lập lại Font. Xong

Tất nhiên như thế thì rách việc quá. Đây chỉ là xử lý tình huống đã rồi mà thôi. Chỉ cùng lắm không xử lý được mới phải "mắng" đối tác thôi.

Tôi mở ra thì có lỗi (do MISSING) và tôi đẫ xử lý như trên. Gọi là chữa cháy, xử lý sự cố đã cháy rồi
 
Lần chỉnh sửa cuối:
Để làm được vậy tôi phải vận dụng nhiều thủ tục của các cao thủ cho bài viết này:

1) Module: mdlPictureExtract (Insert Picture):

Mã:
Option Explicit
''******************************************************************************************************************************
''[COLOR=#ff8c00][B]Written by ndu96081631 - GiaiPhapExcel.com[/B][/COLOR]
''******************************************************************************************************************************
Private Declare Function IsClipboardFormatAvailable Lib "user32" (ByVal wFormat As Integer) As Long
Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Integer) As Long
Private Declare Function CloseClipboard Lib "user32" () As Long
Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" (PicDesc As uPicDesc, RefIID As GUID, ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long
Private Declare Function CopyEnhMetaFile Lib "gdi32" Alias "CopyEnhMetaFileA" (ByVal hemfSrc As Long, ByVal lpszFile As String) As Long
Private Declare Function CopyImage Lib "user32" (ByVal handle As Long, ByVal un1 As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal un2 As Long) As Long
''******************************************************************************************************************************
Private Type GUID
    Data1 As Long
    Data2 As Integer
    Data3 As Integer
    Data4(0 To 7) As Byte
End Type
''******************************************************************************************************************************
Private Type uPicDesc
    Size As Long
    Type As Long
    hPic As Long
    hPal As Long
End Type
''******************************************************************************************************************************


Function PictureFromObject(ByVal Target As Object, Optional ByVal bType As Boolean = True) As IPictureDisp
    Dim hPtr As Long, hCopy As Long, PicType As Long
    Const CF_BITMAP = 2
    Const CF_PALETTE = 9
    Const CF_ENHMETAFILE = 14
    Const IMAGE_BITMAP = 0
    Const LR_COPYRETURNORG = &H4
    Const PicType_BITMAP = 1
    Const PicType_ENHMETAFILE = 4
    
    Target.CopyPicture , IIf(bType, xlBitmap, xlPicture)
    PicType = IIf(IsClipboardFormatAvailable(CF_BITMAP) <> 0, CF_BITMAP, CF_ENHMETAFILE)
    
    If IsClipboardFormatAvailable(PicType) <> 0 Then
        If OpenClipboard(0) > 0 Then
            hPtr = GetClipboardData(PicType)
            If PicType = CF_BITMAP Then
                hCopy = CopyImage(hPtr, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG)
            Else
                hCopy = CopyEnhMetaFile(hPtr, vbNullString)
            End If
            CloseClipboard
            If hPtr <> 0 Then
                Dim uPicInfo As uPicDesc, IID_IDispatch As GUID, IPic As IPictureDisp
                With IID_IDispatch
                    .Data1 = &H7BF80980
                    .Data2 = &HBF32
                    .Data3 = &H101A
                    .Data4(0) = &H8B
                    .Data4(1) = &HBB
                    .Data4(2) = &H0
                    .Data4(3) = &HAA
                    .Data4(4) = &H0
                    .Data4(5) = &H30
                    .Data4(6) = &HC
                    .Data4(7) = &HAB
                End With
                With uPicInfo
                    .Size = Len(uPicInfo)
                    .Type = IIf(PicType = CF_BITMAP, PicType_BITMAP, PicType_ENHMETAFILE)
                    .hPic = hCopy
                End With
                OleCreatePictureIndirect uPicInfo, IID_IDispatch, True, IPic
                Set PictureFromObject = IPic
            End If
        End If
    End If
End Function


2) Module: mdlFormPosition (tính vị trí của cell):

Mã:
Option Explicit
''******************************************************************************************************************************
Private Declare Function GetDC Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32.dll" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Private Declare Function GetDeviceCaps Lib "gdi32.dll" (ByVal hdc As Long, ByVal nIndex As Long) As Long
''******************************************************************************************************************************


Sub LocateForm(ByVal MyForm As Object, ByVal MyRange As Range)
    Dim hdc&, deviceCaps88&, deviceCaps90&
    hdc = GetDC(0)
    deviceCaps88 = GetDeviceCaps(hdc, 88)
    deviceCaps90 = GetDeviceCaps(hdc, 90)
    MyForm.Left = ActiveWindow.PointsToScreenPixelsX _
        (MyRange.Offset(, 1).Left * deviceCaps88 / 72) / deviceCaps88 * 72
    MyForm.Top = ActiveWindow.PointsToScreenPixelsY _
        (MyRange.Top * deviceCaps90 / 72) / deviceCaps90 * 72
    ReleaseDC 0, hdc
End Sub

3) Module: mdlMainCode (thủ tục chính):

Mã:
Option Explicit
''******************************************************************************************************************************
Public pub_Sum As Long
Public pub_Picture As String
Public pub_Height As Double, pub_Width As Double
''******************************************************************************************************************************
Public pub_SumGD As Long, pub_SumDT As Long
Public pub_Height_GD As Double, pub_Width_GD As Double
Public pub_Height_DT As Double, pub_Width_DT As Double
''******************************************************************************************************************************


Sub CreatePicture()
    Dim lRow As Long
    On Error Resume Next
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.DisplayAlerts = False
    Sheets("PictInsert").Visible = xlSheetVisible
    Sheets("PictInsert").Delete
    Application.DisplayAlerts = True
    Sheets.Add
    ActiveSheet.Name = "PictInsert"
    Sheets("PictInsert").Visible = xlSheetVeryHidden
    lRow = GiaDung.Range("B" & Rows.Count).End(xlUp).Row
    pub_SumGD = GiaDung.Range("D" & lRow).Value
    With GiaDung.Range("B3:D" & lRow)
        pub_Height_GD = .Height
        pub_Width_GD = .Width
        .Copy
    End With
    Sheets("PictInsert").Pictures.Paste(Link:=True).Name = "GiaDung"
    
    lRow = DienTu.Range("B" & Rows.Count).End(xlUp).Row
    pub_SumDT = DienTu.Range("D" & lRow).Value
    With DienTu.Range("B3:D" & lRow)
        pub_Height_DT = .Height
        pub_Width_DT = .Width
        .Copy
    End With
    Sheets("PictInsert").Pictures.Paste(Link:=True).Name = "DienTu"
    Application.CutCopyMode = False
    Application.EnableEvents = True
    Application.ScreenUpdating = True
End Sub


Sub PictureSetting()
    Dim PictIns As IPictureDisp, PictExt As Shape
    Set PictExt = Sheets("PictInsert").Shapes(pub_Picture)
    If Not PictExt Is Nothing Then
        Set PictIns = PictureFromObject(PictExt)
        Dim FormHeight As Single, FormWidth As Single
        FormHeight = 200
        FormWidth = 240
        With usfPopup
            .Height = FormHeight
            .Width = FormWidth
            .ScrollLeft = 0
            .ScrollTop = 0
            .ScrollBars = fmScrollBarsNone
            .Picture = PictIns
            If pub_Width > FormWidth And pub_Height > FormHeight Then
                .ScrollBars = fmScrollBarsBoth
                .ScrollHeight = pub_Height
                .ScrollWidth = pub_Width
            ElseIf pub_Width > FormWidth And pub_Height < FormHeight Then
                .ScrollBars = fmScrollBarsHorizontal
                .ScrollWidth = pub_Width
                .Height = pub_Height
            ElseIf pub_Width < FormWidth And pub_Height > FormHeight Then
                .ScrollBars = fmScrollBarsVertical
                .ScrollHeight = pub_Height
                .Width = pub_Width
            Else
                .Height = pub_Height
                .Width = pub_Width
            End If
        End With
    End If
End Sub

4) Sheet Module: Summary (chạy các sự kiện trên sheet):

Mã:
[/B][/U]Option Explicit


Private Sub Worksheet_Activate()
    Call CreatePicture
End Sub


Private Sub Worksheet_Deactivate()
    On Error Resume Next
    Unload usfPopup
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    Sheets("PictInsert").Visible = xlSheetVisible
    Sheets("PictInsert").Delete
    pub_Width_GD = 0
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
End Sub


Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Application.EnableEvents = False
    If pub_Width_GD = 0 Then Call CreatePicture
    usfPopup.Hide
    If Target.Address = "$D$4" Then
        pub_Picture = "GiaDung"
        pub_Height = pub_Height_GD + 12
        pub_Width = pub_Width_GD + 12
        pub_Sum = pub_SumGD
        Call PictureSetting
        usfPopup.Show
    ElseIf Target.Address = "$D$5" Then
        pub_Picture = "DienTu"
        pub_Height = pub_Height_DT + 12
        pub_Width = pub_Width_DT + 12
        pub_Sum = pub_SumDT
        Call PictureSetting
        usfPopup.Show
    End If
    Application.EnableEvents = True
End Sub
[U][B]


5) UserForm Module: usfPopup (chạy các sự kiện trên Form):

Mã:
[/B][/U]Option Explicit
''******************************************************************************************************************************
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" ( _
        ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" ( _
        ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _
        ByVal lpClassName As String, ByVal lpWindowName As String) As Long
''******************************************************************************************************************************
Const WS_BORDER = &H800000
Const WS_CAPTION = &HC00000
Const WS_THICKFRAME = &H40000
Const WS_DLGFRAME = &H400000
Const WS_EX_DLGMODALFRAME = &H1&
Const GWL_STYLE = (-16)
Const GWL_EXSTYLE = (-20)
''******************************************************************************************************************************


Private Sub UserForm_Activate()
    LocateForm Me, Selection
End Sub


Private Sub UserForm_Click()
    If pub_Picture = "GiaDung" Then
        Summary.Range("D4") = pub_Sum
    Else
        Summary.Range("D5") = pub_Sum
    End If
    Unload Me
End Sub


Private Sub UserForm_Initialize()
    Dim TitleHeight As Double, hwnd&
    TitleHeight = Height - InsideHeight
    hwnd = FindWindow("ThunderDFrame", Caption)    'XL2000
    SetWindowLong hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) _
    And Not (WS_BORDER Or WS_CAPTION Or WS_THICKFRAME Or WS_DLGFRAME)
    SetWindowLong hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) _
    And Not WS_EX_DLGMODALFRAME
    Height = Height - TitleHeight
End Sub
''******************************************************************************************************************************
Private Sub UserForm_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    Me.Hide
End Sub
[U][B]

;;;;;;;;;;;Thiệt là cực khổ quá đi đó hả!!! +-+-+-+
 

File đính kèm

Để làm được vậy tôi phải vận dụng nhiều thủ tục của các cao thủ cho bài viết này:

4) Sheet Module: Summary (chạy các sự kiện trên sheet):

Mã:
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Application.EnableEvents = False
    If pub_Width_GD = 0 Then Call CreatePicture
    usfPopup.Hide
    If Target.Address = "$D$4" Then
        pub_Picture = "GiaDung"
        pub_Height = pub_Height_GD [COLOR=#0000cd][B]+ 12[/B][/COLOR]
        pub_Width = pub_Width_GD [B][COLOR=#0000cd]+ 12[/COLOR][/B]
        pub_Sum = pub_SumGD
        Call PictureSetting
        usfPopup.Show
    ElseIf Target.Address = "$D$5" Then
        pub_Picture = "DienTu"
        pub_Height = pub_Height_DT[COLOR=#0000cd] [B]+ 12[/B][/COLOR]
        pub_Width = pub_Width_DT [B][COLOR=#0000cd]+ 12[/COLOR][/B]
        pub_Sum = pub_SumDT
        Call PictureSetting
        usfPopup.Show
    End If
    Application.EnableEvents = True
End Sub
;;;;;;;;;;;Thiệt là cực khổ quá đi đó hả!!! +-+-+-+

Với số + 12 của sự kiện trên, bạn có thể sẽ không thể thấy hết toàn bộ hình ảnh trên một số máy, thôi thì tăng "số hiệu chỉnh" là 125% đi cho chắc ăn:

Mã:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Application.EnableEvents = False
    If pub_Width_GD = 0 Then Call CreatePicture
    usfPopup.Hide
    If Target.Address = "$D$4" Then
        pub_Picture = "GiaDung"
        pub_Height = pub_Height_GD[COLOR=#0000cd][B] * 1.25[/B][/COLOR]
        pub_Width = pub_Width_GD [COLOR=#0000cd][B]* 1.25[/B][/COLOR]
        pub_Sum = pub_SumGD
        Call PictureSetting
        usfPopup.Show
    ElseIf Target.Address = "$D$5" Then
        pub_Picture = "DienTu"
        pub_Height = pub_Height_DT [B][COLOR=#0000cd]* 1.25[/COLOR][/B]
        pub_Width = pub_Width_DT [COLOR=#0000cd][B]* 1.25[/B][/COLOR]
        pub_Sum = pub_SumDT
        Call PictureSetting
        usfPopup.Show
    End If
    Application.EnableEvents = True
End Sub
 
Để làm được vậy tôi phải vận dụng nhiều thủ tục của các cao thủ cho bài viết này:

1) Module: mdlPictureExtract (Insert Picture):

Mã:
Option Explicit
''******************************************************************************************************************************
''[COLOR=#ff8c00][B]Written by ndu96081631 - GiaiPhapExcel.com[/B][/COLOR]
''******************************************************************************************************************************
Private Declare Function IsClipboardFormatAvailable Lib "user32" (ByVal wFormat As Integer) As Long
Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Integer) As Long
Private Declare Function CloseClipboard Lib "user32" () As Long
Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" (PicDesc As uPicDesc, RefIID As GUID, ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long
Private Declare Function CopyEnhMetaFile Lib "gdi32" Alias "CopyEnhMetaFileA" (ByVal hemfSrc As Long, ByVal lpszFile As String) As Long
Private Declare Function CopyImage Lib "user32" (ByVal handle As Long, ByVal un1 As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal un2 As Long) As Long
''******************************************************************************************************************************
Private Type GUID
    Data1 As Long
    Data2 As Integer
    Data3 As Integer
    Data4(0 To 7) As Byte
End Type
''******************************************************************************************************************************
Private Type uPicDesc
    Size As Long
    Type As Long
    hPic As Long
    hPal As Long
End Type
''******************************************************************************************************************************


Function PictureFromObject(ByVal Target As Object, Optional ByVal bType As Boolean = True) As IPictureDisp
    Dim hPtr As Long, hCopy As Long, PicType As Long
    Const CF_BITMAP = 2
    Const CF_PALETTE = 9
    Const CF_ENHMETAFILE = 14
    Const IMAGE_BITMAP = 0
    Const LR_COPYRETURNORG = &H4
    Const PicType_BITMAP = 1
    Const PicType_ENHMETAFILE = 4
    
    Target.CopyPicture , IIf(bType, xlBitmap, xlPicture)
    PicType = IIf(IsClipboardFormatAvailable(CF_BITMAP) <> 0, CF_BITMAP, CF_ENHMETAFILE)
    
    If IsClipboardFormatAvailable(PicType) <> 0 Then
        If OpenClipboard(0) > 0 Then
            hPtr = GetClipboardData(PicType)
            If PicType = CF_BITMAP Then
                hCopy = CopyImage(hPtr, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG)
            Else
                hCopy = CopyEnhMetaFile(hPtr, vbNullString)
            End If
            CloseClipboard
            If hPtr <> 0 Then
                Dim uPicInfo As uPicDesc, IID_IDispatch As GUID, IPic As IPictureDisp
                With IID_IDispatch
                    .Data1 = &H7BF80980
                    .Data2 = &HBF32
                    .Data3 = &H101A
                    .Data4(0) = &H8B
                    .Data4(1) = &HBB
                    .Data4(2) = &H0
                    .Data4(3) = &HAA
                    .Data4(4) = &H0
                    .Data4(5) = &H30
                    .Data4(6) = &HC
                    .Data4(7) = &HAB
                End With
                With uPicInfo
                    .Size = Len(uPicInfo)
                    .Type = IIf(PicType = CF_BITMAP, PicType_BITMAP, PicType_ENHMETAFILE)
                    .hPic = hCopy
                End With
                OleCreatePictureIndirect uPicInfo, IID_IDispatch, True, IPic
                Set PictureFromObject = IPic
            End If
        End If
    End If
End Function


2) Module: mdlFormPosition (tính vị trí của cell):

Mã:
Option Explicit
''******************************************************************************************************************************
Private Declare Function GetDC Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32.dll" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Private Declare Function GetDeviceCaps Lib "gdi32.dll" (ByVal hdc As Long, ByVal nIndex As Long) As Long
''******************************************************************************************************************************


Sub LocateForm(ByVal MyForm As Object, ByVal MyRange As Range)
    Dim hdc&, deviceCaps88&, deviceCaps90&
    hdc = GetDC(0)
    deviceCaps88 = GetDeviceCaps(hdc, 88)
    deviceCaps90 = GetDeviceCaps(hdc, 90)
    MyForm.Left = ActiveWindow.PointsToScreenPixelsX _
        (MyRange.Offset(, 1).Left * deviceCaps88 / 72) / deviceCaps88 * 72
    MyForm.Top = ActiveWindow.PointsToScreenPixelsY _
        (MyRange.Top * deviceCaps90 / 72) / deviceCaps90 * 72
    ReleaseDC 0, hdc
End Sub

3) Module: mdlMainCode (thủ tục chính):

Mã:
Option Explicit
''******************************************************************************************************************************
Public pub_Sum As Long
Public pub_Picture As String
Public pub_Height As Double, pub_Width As Double
''******************************************************************************************************************************
Public pub_SumGD As Long, pub_SumDT As Long
Public pub_Height_GD As Double, pub_Width_GD As Double
Public pub_Height_DT As Double, pub_Width_DT As Double
''******************************************************************************************************************************


Sub CreatePicture()
    Dim lRow As Long
    On Error Resume Next
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.DisplayAlerts = False
    Sheets("PictInsert").Visible = xlSheetVisible
    Sheets("PictInsert").Delete
    Application.DisplayAlerts = True
    Sheets.Add
    ActiveSheet.Name = "PictInsert"
    Sheets("PictInsert").Visible = xlSheetVeryHidden
    lRow = GiaDung.Range("B" & Rows.Count).End(xlUp).Row
    pub_SumGD = GiaDung.Range("D" & lRow).Value
    With GiaDung.Range("B3:D" & lRow)
        pub_Height_GD = .Height
        pub_Width_GD = .Width
        .Copy
    End With
    Sheets("PictInsert").Pictures.Paste(Link:=True).Name = "GiaDung"
    
    lRow = DienTu.Range("B" & Rows.Count).End(xlUp).Row
    pub_SumDT = DienTu.Range("D" & lRow).Value
    With DienTu.Range("B3:D" & lRow)
        pub_Height_DT = .Height
        pub_Width_DT = .Width
        .Copy
    End With
    Sheets("PictInsert").Pictures.Paste(Link:=True).Name = "DienTu"
    Application.CutCopyMode = False
    Application.EnableEvents = True
    Application.ScreenUpdating = True
End Sub


Sub PictureSetting()
    Dim PictIns As IPictureDisp, PictExt As Shape
    Set PictExt = Sheets("PictInsert").Shapes(pub_Picture)
    If Not PictExt Is Nothing Then
        Set PictIns = PictureFromObject(PictExt)
        Dim FormHeight As Single, FormWidth As Single
        FormHeight = 200
        FormWidth = 240
        With usfPopup
            .Height = FormHeight
            .Width = FormWidth
            .ScrollLeft = 0
            .ScrollTop = 0
            .ScrollBars = fmScrollBarsNone
            .Picture = PictIns
            If pub_Width > FormWidth And pub_Height > FormHeight Then
                .ScrollBars = fmScrollBarsBoth
                .ScrollHeight = pub_Height
                .ScrollWidth = pub_Width
            ElseIf pub_Width > FormWidth And pub_Height < FormHeight Then
                .ScrollBars = fmScrollBarsHorizontal
                .ScrollWidth = pub_Width
                .Height = pub_Height
            ElseIf pub_Width < FormWidth And pub_Height > FormHeight Then
                .ScrollBars = fmScrollBarsVertical
                .ScrollHeight = pub_Height
                .Width = pub_Width
            Else
                .Height = pub_Height
                .Width = pub_Width
            End If
        End With
    End If
End Sub

4) Sheet Module: Summary (chạy các sự kiện trên sheet):

Mã:
Mã:
Option Explicit


Private Sub Worksheet_Activate()
    Call CreatePicture
End Sub


Private Sub Worksheet_Deactivate()
    On Error Resume Next
    Unload usfPopup
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    Sheets("PictInsert").Visible = xlSheetVisible
    Sheets("PictInsert").Delete
    pub_Width_GD = 0
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
End Sub


Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Application.EnableEvents = False
    If pub_Width_GD = 0 Then Call CreatePicture
    usfPopup.Hide
    If Target.Address = "$D$4" Then
        pub_Picture = "GiaDung"
        pub_Height = pub_Height_GD + 12
        pub_Width = pub_Width_GD + 12
        pub_Sum = pub_SumGD
        Call PictureSetting
        usfPopup.Show
    ElseIf Target.Address = "$D$5" Then
        pub_Picture = "DienTu"
        pub_Height = pub_Height_DT + 12
        pub_Width = pub_Width_DT + 12
        pub_Sum = pub_SumDT
        Call PictureSetting
        usfPopup.Show
    End If
    Application.EnableEvents = True
End Sub
5) UserForm Module: usfPopup (chạy các sự kiện trên Form):

Mã:
Mã:
Option Explicit
''******************************************************************************************************************************
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" ( _
        ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" ( _
        ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _
        ByVal lpClassName As String, ByVal lpWindowName As String) As Long
''******************************************************************************************************************************
Const WS_BORDER = &H800000
Const WS_CAPTION = &HC00000
Const WS_THICKFRAME = &H40000
Const WS_DLGFRAME = &H400000
Const WS_EX_DLGMODALFRAME = &H1&
Const GWL_STYLE = (-16)
Const GWL_EXSTYLE = (-20)
''******************************************************************************************************************************


Private Sub UserForm_Activate()
    LocateForm Me, Selection
End Sub


Private Sub UserForm_Click()
    If pub_Picture = "GiaDung" Then
        Summary.Range("D4") = pub_Sum
    Else
        Summary.Range("D5") = pub_Sum
    End If
    Unload Me
End Sub


Private Sub UserForm_Initialize()
    Dim TitleHeight As Double, hwnd&
    TitleHeight = Height - InsideHeight
    hwnd = FindWindow("ThunderDFrame", Caption)    'XL2000
    SetWindowLong hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) _
    And Not (WS_BORDER Or WS_CAPTION Or WS_THICKFRAME Or WS_DLGFRAME)
    SetWindowLong hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) _
    And Not WS_EX_DLGMODALFRAME
    Height = Height - TitleHeight
End Sub
''******************************************************************************************************************************
Private Sub UserForm_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    Me.Hide
End Sub
;;;;;;;;;;;Thiệt là cực khổ quá đi đó hả!!! +-+-+-+

Sao bạn lại khổ thế hả bạn?

Bạn đi vòng vèo nên mệt là phải rồi. Không mệt mới là chuyện lạ.

Bạn làm: copy range vào clipboard --> tạo sheet ẩn --> tạo trên sheet ẩn object Picture lấy từ clipboard --> sau đó lại copy cái Picture (shape) ngược trở lại vào clipboard --> lấy từ clipboard ra để tạo object IPictureDisp --> "nhồi vào UserForm

Toàn bộ khâu nhiều việc đỏ đỏ là không cần thiết

code của tôi

sheet
Mã:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim lastRow As Long, picHandle As Long
    If Target.Address = "$D$4" Then
        lastRow = GiaDung.Range("B" & Rows.Count).End(xlUp).Row
        picHandle = RangeToHBITMAP(GiaDung.Range("B3:D" & lastRow))
        UserForm1.Picture = HBITMAPToIPicture(picHandle)
        UserForm1.Show
    ElseIf Target.Address = "$D$5" Then
        lastRow = DienTu.Range("B" & Rows.Count).End(xlUp).Row
        picHandle = RangeToHBITMAP(DienTu.Range("B3:D" & lastRow))
        UserForm1.Picture = HBITMAPToIPicture(picHandle)
        UserForm1.Show
    End If
End Sub

modPicture
Mã:
Const PICTYPE_BITMAP = 1
Const CF_BITMAP = 2
Const IMAGE_BITMAP = 0
Const LR_COPYRETURNORG = &H4

' GUID
Private Type GUID
    D1 As Long
    D2 As Integer
    D3 As Integer
    D4(0 To 7) As Byte
End Type

Private Type PictDesc
    cbSizeofStruct As Long
    picType As Long
    hImage As Long
    hPal As Long
End Type

Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As Long
Private Declare Function CloseClipboard Lib "user32" () As Long

Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" (lpPictDesc As PictDesc, riid As GUID, ByVal fOwn As Long, lplpvObj As Any) As Long
Private Declare Function CopyImage Lib "user32" (ByVal handle As Long, ByVal un1 As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal un2 As Long) As Long

Function RangeToHBITMAP(rng As Range) As Long
Dim hRes As Long
    rng.Copy
    OpenClipboard 0
    
    hRes = GetClipboardData(CF_BITMAP)
    If hRes <> 0 Then RangeToHBITMAP = CopyImage(hRes, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG)
    CloseClipboard
    Application.CutCopyMode = False
End Function

Function HBITMAPToIPicture(ByVal hbmp As Long) As IPictureDisp
Dim lpPictDesc As PictDesc, riid As GUID, pic As IPictureDisp
    If hbmp <> 0 Then
'        GUID cua Interface IPicture - {7BF80980-BF32-101A-8BBB-00AA00300CAB}
        With riid
            .D1 = &H7BF80980
            .D2 = &HBF32
            .D3 = &H101A
            .D4(0) = &H8B
            .D4(1) = &HBB
            .D4(2) = &H0
            .D4(3) = &HAA
            .D4(4) = &H0
            .D4(5) = &H30
            .D4(6) = &HC
            .D4(7) = &HAB
        End With
        With lpPictDesc
            .cbSizeofStruct = Len(lpPictDesc)
            .picType = PICTYPE_BITMAP  
            .hImage = hbmp
            .hPal = 0
        End With
        If OleCreatePictureIndirect(lpPictDesc, riid, True, pic) = 0 Then
            Set HBITMAPToIPicture = pic
        End If
    End If
End Function

UserForm
Mã:
Private Sub UserForm_Click()
    Unload Me
End Sub

Tất nhiên tôi không làm: bỏ thanh tiêu đề của Form, xác định kích thước, ̣định vị Form, thêm thanh trượt.
Không làm vì chỉ muốn nhấn mạnh cách tạo Picture mà thôi.
 

File đính kèm

Cảm ơn các bác rất nhiều, đặc biệt là 2 bác Hoàng Trọng Nghĩa và phucbugis đã bỏ thời gian và công sức làm cho em 2 cái file rất pro ^_^

Ở máy của em thì Form của bác phucbugis hoạt động bình thường. Có điều là các Code trong này hơi "cao siêu" so với trình của em **~**, chắc phải ít thời gian nữa mới lĩnh hội được.

Các bác cho em hỏi là 2 cách làm này về cơ bản khác nhau như thế nào ạ? Em đang phân vân không biết nên làm theo cái nào.
 
Sao bạn lại khổ thế hả bạn?
....
Tất nhiên tôi không làm: bỏ thanh tiêu đề của Form, xác định kích thước, ̣định vị Form, thêm thanh trượt.
Không làm vì chỉ muốn nhấn mạnh cách tạo Picture mà thôi.

xin bác xem lại, khi e chèn thêm hàng bên sheet Giadung thì popup nó ra thế này
siwtom.png
 
Sao bạn lại khổ thế hả bạn?

Bạn đi vòng vèo nên mệt là phải rồi. Không mệt mới là chuyện lạ.

Bạn làm: copy range vào clipboard --> tạo sheet ẩn --> tạo trên sheet ẩn object Picture lấy từ clipboard --> sau đó lại copy cái Picture (shape) ngược trở lại vào clipboard --> lấy từ clipboard ra để tạo object IPictureDisp --> "nhồi vào UserForm

Toàn bộ khâu nhiều việc đỏ đỏ là không cần thiết

code của tôi

sheet
Mã:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim lastRow As Long, picHandle As Long
    If Target.Address = "$D$4" Then
        lastRow = GiaDung.Range("B" & Rows.Count).End(xlUp).Row
        picHandle = RangeToHBITMAP(GiaDung.Range("B3:D" & lastRow))
        UserForm1.Picture = HBITMAPToIPicture(picHandle)
        UserForm1.Show
    ElseIf Target.Address = "$D$5" Then
        lastRow = DienTu.Range("B" & Rows.Count).End(xlUp).Row
        picHandle = RangeToHBITMAP(DienTu.Range("B3:D" & lastRow))
        UserForm1.Picture = HBITMAPToIPicture(picHandle)
        UserForm1.Show
    End If
End Sub

modPicture
Mã:
Const PICTYPE_BITMAP = 1
Const CF_BITMAP = 2
Const IMAGE_BITMAP = 0
Const LR_COPYRETURNORG = &H4

' GUID
Private Type GUID
    D1 As Long
    D2 As Integer
    D3 As Integer
    D4(0 To 7) As Byte
End Type

Private Type PictDesc
    cbSizeofStruct As Long
    picType As Long
    hImage As Long
    hPal As Long
End Type

Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As Long
Private Declare Function CloseClipboard Lib "user32" () As Long

Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" (lpPictDesc As PictDesc, riid As GUID, ByVal fOwn As Long, lplpvObj As Any) As Long
Private Declare Function CopyImage Lib "user32" (ByVal handle As Long, ByVal un1 As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal un2 As Long) As Long

Function RangeToHBITMAP(rng As Range) As Long
Dim hRes As Long
    rng.Copy
    OpenClipboard 0
    
    hRes = GetClipboardData(CF_BITMAP)
    If hRes <> 0 Then RangeToHBITMAP = CopyImage(hRes, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG)
    CloseClipboard
    Application.CutCopyMode = False
End Function

Function HBITMAPToIPicture(ByVal hbmp As Long) As IPictureDisp
Dim lpPictDesc As PictDesc, riid As GUID, pic As IPictureDisp
    If hbmp <> 0 Then
'        GUID cua Interface IPicture - {7BF80980-BF32-101A-8BBB-00AA00300CAB}
        With riid
            .D1 = &H7BF80980
            .D2 = &HBF32
            .D3 = &H101A
            .D4(0) = &H8B
            .D4(1) = &HBB
            .D4(2) = &H0
            .D4(3) = &HAA
            .D4(4) = &H0
            .D4(5) = &H30
            .D4(6) = &HC
            .D4(7) = &HAB
        End With
        With lpPictDesc
            .cbSizeofStruct = Len(lpPictDesc)
            .picType = PICTYPE_BITMAP  
            .hImage = hbmp
            .hPal = 0
        End With
        If OleCreatePictureIndirect(lpPictDesc, riid, True, pic) = 0 Then
            Set HBITMAPToIPicture = pic
        End If
    End If
End Function

UserForm
Mã:
Private Sub UserForm_Click()
    Unload Me
End Sub

Tất nhiên tôi không làm: bỏ thanh tiêu đề của Form, xác định kích thước, ̣định vị Form, thêm thanh trượt.
Không làm vì chỉ muốn nhấn mạnh cách tạo Picture mà thôi.

Vâng cám ơn Thầy vì đã hướng dẫn cách này, bởi cái thủ tục Insert Picture đó là học (nói đúng ra là sao chép toàn bộ) của Thầy NDU vì thấy nó hay quá mà em chưa thể tự mình nghiên cứu được khi phải trả lời ngay bài này ạ.

Cám ơn Thầy đã chỉ cho một hướng đi ngắn gọn.
 
Cảm ơn các bác rất nhiều, đặc biệt là 2 bác Hoàng Trọng Nghĩa và phucbugis đã bỏ thời gian và công sức làm cho em 2 cái file rất pro ^_^
Ở máy của em thì Form của bác phucbugis hoạt động bình thường. Có điều là các Code trong này hơi "cao siêu" so với trình của em **~**, chắc phải ít thời gian nữa mới lĩnh hội được.
Các bác cho em hỏi là 2 cách làm này về cơ bản khác nhau như thế nào ạ? Em đang phân vân không biết nên làm theo cái nào.

nếu đơn giản chỉ cần Popup thì bạn chọn cách làm của bác HTN, còn muốn đi xa hơn nữa (ví dụ như tìm kiếm, update, chỉnh sửa số liệu trực tiếp từ sheet SUMMARY thì nên đi theo hướng của mình --=0)
 
Lần chỉnh sửa cuối:
Web KT

Bài viết mới nhất

Back
Top Bottom