分享

Excel VBA 用户管理/Usf_AddAndModify窗体代码

 冷茶视界 2023-11-15 发布于江苏

☆本期内容概要☆

  • 用户窗体设置:用户管理代码-

由于是从别的应用中复制过来的用户窗体,有部分代码没有删除干净,待后续调整,目前仅有限测试通过。

Private Declare PtrSafe Function SendMessageLong Lib "user32" Alias "SendMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As LongPtr, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr

Private Declare PtrSafe Function GetScrollPos Lib "user32" (ByVal hwnd As LongPtr, ByVal nBar As LongPtr) As LongPtr

Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As Long

Private Declare PtrSafe Function GetDeviceCaps Lib "gdi32" (ByVal hDC As Long, ByVal nIndex As Long) As Long

Private Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hwnd As LongPtr, ByVal hDC As LongPtr) As LongPtr

Private Const LVM_FIRST = &H1000

Private Const LVM_SCROLL = (LVM_FIRST + 20)

Private Const SB_HORZ = 0

Private Const LOGPIXELSX = 88

Private EditableCol As String                    '窗体初始化时指定可以编辑的列号,如"01/03/10"

Private EditableField As String                  '可编辑表头字段,根据它来转化成EditableCol

Private strRequiredCol As String                 '必填列,如"01/03/10",数据库中自动编号不能设置

Private strRequiredField As String               '必填字段,根据它来转化成strRequiredCol

Private sngPixelPerPoint As Double               '每像素的磅数,窗体初始化时计算一次即可

Private intCol As Integer                        '记录ListView第几列被点击,Listview标题索引从1开始

Private blnFlag As Boolean                       '按下Escape键时,指示InkEdit1_Exit事件不保存修改

'Private blnNewItem As Boolean                    '新增一行标识符。如果新增行未保存或未删除,该标识为TRUE

Private strOriginal As String                    '记录每次显示InkEdit时的原始值,用于其退出时的比较

Private arrData As Variant                       '数据数组,如果连接数据库,请使用ADO的Recordset对象

Dim p As Long

Dim SortType As Integer

Dim iTotal As Double

Dim DicMonth

Dim aData()

Dim iRow

Dim iCol

Dim tbTitle(), sTbtitle()

Dim arrStr() As String

Dim ItemStr As String

Dim ModifyStatus As Integer                      '修改状态,点

Dim DeleteStatus As Integer                      '删除状态,记录是否有删除动作

Dim arrModifyCode()                              '修改的科目代码

Dim arrModifyItems()

Dim arrOldItems(), arrNewItems()

Dim LvItem As ListItem

Dim arrWidth()

Dim arr(), arrType() 'Usf_Interm 中组合框数据源

Dim preDate As Date

Dim preColor

Dim preNumber As Integer

Dim intRow As Integer    'selecteditems的行号

'Dim AccCode As String, AccName As String

Dim CheckBoxStatus As Boolean

Dim strDeletedId As String

Dim strDeletedAccCode As String

Dim initSQL As String     'listview初始化数据的sql,在保存后再调用重新加载数据

Dim strModifiedID As String

Dim intStrikeTimes As Integer  '记录Esc键的按键次数

Dim lastEscapeTime As Single  '记录第一次按下ESC的时间

Private Sub Cmd_Exit_Click()

    If ModifyStatus > 0 Or DeleteStatus > 0 Then

        If Not wContinue("所有未保存的操作将丢失!") Then Exit Sub

    End If

    Call RestoreAPI

    ModifyStatus = 0

    DeleteStatus = 0

    Unload Me

End Sub

Private Sub AddNewItem(Optional ByVal AddPos As String = "end")

    Dim IDX As Integer

    If ShiftKeyPressed Then

        If AddPos = "before" Then

            AddPos = "after"

        ElseIf AddPos = "after" Then

            AddPos = "before"

        End If

    End If

    If Me.LvDetail.ListItems.Count = 0 Then

        IDX = 1

    Else

        If AddPos = "end" Then

            IDX = Me.LvDetail.ListItems.Count + 1

        ElseIf AddPos = "top" Then

            IDX = 1

        ElseIf AddPos = "before" Then

            If Me.LvDetail.SelectedItem.index = 1 Then

                IDX = 1

            Else

                IDX = Me.LvDetail.SelectedItem.index - 1

            End If

        ElseIf AddPos = "after" Then

            IDX = Me.LvDetail.SelectedItem.index + 1

        Else

            IDX = Me.LvDetail.ListItems.Count + 1

        End If

    End If

    '根据指定字段转化可编辑列、必填列

    With Me.LvDetail

        For i = 1 To .ColumnHeaders.Count

            If InStr(EditableField, "All") Then

                If .ColumnHeaders(i) <> "ID" Then

                    EditableCol = EditableCol & Format(i, "00") & "/"

                End If

            ElseIf InStr(EditableField, "Except") Then

                If .ColumnHeaders(i) <> "ID" And InStr(EditableField, .ColumnHeaders(i)) = 0 Then

                    EditableCol = EditableCol & Format(i, "00") & "/"

                End If

            Else

                If InStr(EditableField, .ColumnHeaders(i)) Then

                    EditableCol = EditableCol & Format(i, "00") & "/"

                End If

            End If

        Next

    End With

    'Stop

    With Me.LvDetail

        Set LvItem = .ListItems.Add(IDX, , "")

        If currTable = "tb凭证" Then

            LvItem.SubItems(7) = 0: LvItem.SubItems(8) = 0

            LvItem.SubItems(3) = .ListItems(.ListItems.Count - 1).SubItems(3)

        ElseIf currTable = "tb期初余额" Then

            LvItem.SubItems(1) = CDate(currYear & "/1/1")

            LvItem.SubItems(2) = "期初余额"

            LvItem.SubItems(7) = 0

        End If

        .ListItems(IDX).EnsureVisible

    End With

    ModifyStatus = ModifyStatus + 1

End Sub

Private Sub CmdAddNew_Click()

    Call AddNewItem("after")

End Sub

Private Sub CmdChangeColWidth_Click()

    Dim lvWidth As Double

    If Me.CmdChangeColWidth.Caption = "解冻列宽" Then

        Me.FrmHeader.Visible = False

        Me.LvDetail.HideColumnHeaders = False

        Me.LvDetail.Top = Me.FrmHeader.Top

        Me.CmdChangeColWidth.Caption = "固定列宽"

    ElseIf Me.CmdChangeColWidth.Caption = "固定列宽" Then

        Me.FrmHeader.Visible = True

        With Me.LvDetail

            For i = 1 To .ColumnHeaders.Count

                .ColumnHeaders(i).Width = arrWidth(i - 1)

                lvWidth = lvWidth + arrWidth(i - 1)

            Next

            .HideColumnHeaders = True

            .Top = Me.FrmHeader.Top + Me.FrmHeader.Height

            .Width = lvWidth

            If currTable = "tb凭证" Then

                Me.Width = lvWidth + 20 + 20

            Else

                Me.Width = lvWidth + 20

            End If

        End With

        Me.CmdChangeColWidth.Caption = "解冻列宽"

        Me.CmdChangeColWidth.Left = Me.LvDetail.Left + Me.LvDetail.Width - Me.CmdChangeColWidth.Width

        Me.CmdChangeWidth.Left = Me.CmdChangeColWidth.Left - Me.CmdChangeWidth.Width - 2

        Me.Frame3.Left = Me.LvDetail.Left + Me.LvDetail.Width - Me.Frame3.Width

    End If

End Sub

Private Sub CmdCopyRecord_Click()

    Call AddNewItem("after")

    For j = 1 To LvDetail.ColumnHeaders.Count - 1

        LvItem.SubItems(j) = Me.LvDetail.SelectedItem.SubItems(j)

    Next

End Sub

Private Sub CmdDateDown_Click()

    Dim temDate

    If Me.TxbDate = "" Then Exit Sub

    preMonth = Month(CDate(Me.TxbDate))

    temDate = CDate(Me.TxbDate) - 1

    If VoucherProcType = "凭证修改" Then

        If Month(temDate) <> preMonth Then

            Me.TxbDate = temDate + 1

        Else

            Me.TxbDate = temDate

        End If

    Else

        If Year(temDate) < Val(currYear) Then

            Me.TxbDate = CDate(currYear & "/1/1")

        Else

            Me.TxbDate = temDate

        End If

    End If

End Sub

Private Sub CmdDateUp_Click()

    Dim temDate

    If Me.TxbDate = "" Then Exit Sub

    preMonth = Month(CDate(Me.TxbDate))

    temDate = CDate(Me.TxbDate) + 1

    If VoucherProcType = "凭证修改" Then

        If Month(temDate) <> preMonth Then

            Me.TxbDate = temDate - 1

        Else

            Me.TxbDate = temDate

        End If

    Else

        If Year(temDate) > Val(currYear) Then

            Me.TxbDate = CDate(currYear & "/12/31")

        Else

            Me.TxbDate = temDate

        End If

    End If

End Sub

Private Sub CmdDelete_Click()

    Dim AccountCode As String

    Dim AccTypeCode As String

    Dim ItemName As String

    Dim ItemTypeCode As String

    Dim UserName As String

    Dim arr()

    strDeletedId = ""

    strDeletedAccCode = ""

    With LvDetail

        For i = 1 To .ListItems.Count

            If .ListItems(i).Checked = True Then

                If .ListItems(i).Text <> "" Then

                    '把删除的id记录下来

                    strDeletedId = strDeletedId & Me.LvDetail.ListItems(i).Text & "/"

                End If

                s = s + 1

            End If

        Next

    End With

    If s = 0 Then

        MsgBox "请钩选想要删除的记录!"

        Exit Sub

    End If

    'Stop

    With Me.LvDetail

        For i = .ListItems.Count To 1 Step -1

            If .ListItems(i).Checked = True Then

                .ListItems.Remove (i)

            End If

        Next

    End With

    DeleteStatus = DeleteStatus + 1

    'Stop

End Sub

Private Sub CmdIncreaseHeight_Click()

    Dim H As Integer

    If ShiftKeyPressed Then

        Me.CmdIncreaseHeight.Caption = "减高"

        Me.CmdIncreaseHeight.ForeColor = vbBlack

        H = -20

    Else

        Me.CmdIncreaseHeight.Caption = "增高"

        Me.CmdIncreaseHeight.ForeColor = &HFF00FF

        H = 20

    End If

    Me.Height = Me.Height + H

    Me.LvDetail.Height = Me.LvDetail.Height + H

    Me.Frame3.Top = Me.Frame3.Top + H

End Sub

Private Sub CmdNumberDown_Click()

   If VoucherProcType = "凭证修改" Then Exit Sub

    Me.TxbNumber = IIf(Me.TxbNumber - 1 > 0, Me.TxbNumber - 1, 1)

End Sub

Private Sub CmdNumberUp_Click()

If VoucherProcType = "凭证修改" Then Exit Sub

    Me.TxbNumber = IIf(Me.TxbNumber + 1 < 999, Me.TxbNumber + 1, 999)

End Sub

Private Sub CmdOutPut_Click()

    If Not wContinue("即将导出!") Then Exit Sub

    On Error Resume Next

    Dim arrT()

    Dim iPath As String, iYear As String

    Dim iSheet As Worksheet

    If Me.CkB_ChoseFolder.Value = True Then

        iPath = PathSelected & "\"

    Else

        iPath = ThisWorkbook.Path & "\"

    End If

    fName = Me.LbTitle & Format(VBA.Now, "YYYYMMDDhhmmss") & ".xlsx"

    Application.DisplayAlerts = False

    iRow = Me.LvDetail.ListItems.Count + 1

    iCol = Me.LvDetail.ColumnHeaders.Count

    ReDim arrT(1 To iRow, 1 To iCol)

    For i = 1 To iCol

        arrT(1, i) = Me.LvDetail.ColumnHeaders(i)

    Next

    For i = 2 To iRow

        arrT(i, 1) = Me.LvDetail.ListItems(i - 1).Text

        For j = 2 To iCol

            arrT(i, j) = Me.LvDetail.ListItems(i - 1).SubItems(j - 1)

        Next

    Next

    Workbooks.Add

    ActiveWorkbook.Sheets(1).Range("A1").Resize(iRow, iCol) = arrT

    ActiveWorkbook.SaveAs Filename:=iPath & fName

    ActiveWorkbook.Close

    MsgBox ("成功导出文件" & iPath & fName)

    Unload Me

    Application.DisplayAlerts = True

End Sub

Private Sub CmdSave_Click()

    Dim arrTable()

    Dim LvItem As ListItem

    Dim NullCount As Integer

    Dim arrID() As String       '先不确定数据类型,用来存放split(strdeletedid)

    Dim arrAccCode() As String

    On Error Resume Next

    If CmdChangeColWidth.Caption = "固定列宽" Then

        Call CmdChangeColWidth_Click

    End If

    If ModifyStatus = 0 And DeleteStatus = 0 Then

        MsgBox "数据无任何修改,无需保存!"

        Exit Sub

    End If

    '检查数据完整性、准确性↓↓↓↓↓↓↓↓↓↓↓↓↓↓

    '1、检查必填项是否为空

    With Me.LvDetail

        For i = 1 To .ListItems.Count

            If .ListItems(i).Text = "" Then

                For j = 2 To .ColumnHeaders.Count

                    If InStr(strRequiredCol, Format(j, "00")) Then

                        If .ListItems(i).SubItems(j - 1) = "" Then

                            MsgBox "第【" & j & "】列【" & .ColumnHeaders(j) & "】不能为空!"

                            'Stop

                            Exit Sub

                        End If

                    End If

                Next

            Else

            End If

        Next

    End With

    '检查数据完整性、准确性↑↑↑↑↑↑↑↑↑↑↑↑↑↑

    '删除记录

    If Len(Replace(strDeletedId, "/", "")) > 0 Then

        'Stop

        strDeletedId = Left(strDeletedId, Len(strDeletedId) - 1)

        arrID = Split(strDeletedId, "/")

        If Not wContinue("即将删除以下ID的记录:" & Chr(10) & strDeletedId & Chr(10) & "此操作不可恢复,请谨慎执行!") Then Exit Sub

        SQL = "delete * from " & currTable & " where id in (" & Join(arrID, ",") & ")"

       Call ExecuteSQL(dataFile, SQL)

    End If

    '增加、修改记录,建立数据连接

    Set cnn = CreateObject("ADODB.Connection")

    Set rs = CreateObject("ADODB.Recordset")

    passWord = "p111111"

    StrCnn = GetStrCnn(dataFile, passWord)

    cnn.Open StrCnn

    rs.Open currTable, cnn, 1, 3

    With Me.LvDetail

        For i = 1 To .ListItems.Count

            If Len(Trim(.ListItems(i).Text)) > 0 Then '对id不为空的记录,即可能被修改的记录进行操作

                If InStr(strModifiedID, .ListItems(i).Text) Then               '判断存放id的数组是否为空值,如果为空,则表明没有修改的记录,不用执行更新

                    rs.movefirst

                    Do Until rs.EOF

                        If rs!ID = .ListItems(i).Text Then

                            'rs.Edit

                            For k = 1 To .ColumnHeaders.Count - 1

                                '数据库中“是/否”字段值为“-1/0”,但显示为“true/false”

                                rs.Fields(k) = IIf(.ListItems(i).SubItems(k) = "true", -1, IIf(.ListItems(i).SubItems(k) = "false", 0, .ListItems(i).SubItems(k)))

                            Next

                            rs.Update

                        End If

                        rs.MoveNext

                      Loop

                  End If

                  Else                                 '对id为空的记录,即新增的记录进行操作,向数据库写入记录

                        rs.AddNew

                        For k = 1 To .ColumnHeaders.Count - 1

                            rs.Fields(k) = IIf(.ListItems(i).SubItems(k) = "true", -1, IIf(.ListItems(i).SubItems(k) = "false", 0, .ListItems(i).SubItems(k)))

                        Next

                        rs.Update

                 End If

              Next

        End With

    rs.Close

    cnn.Close

    Set rs = Nothing

    Set cnn = Nothing

        If currTable = "tb凭证" Then

            If VoucherProcType = "凭证制单" Then

                MsgBox "成功保存凭证【" & Me.TxbNumber & "】号!", , Me.LbTitle

            ElseIf VoucherProcType = "凭证修改" Then

                MsgBox "成功修改凭证【" & Me.TxbNumber & "】号!", , Me.LbTitle

            End If

        Else

            MsgBox "保存成功!", , Me.LbTitle

        End If

        ModifyStatus = 0

        strDeletedId = ""

        DeleteStatus = 0

        Me.LvDetail.ColumnHeaders.Clear

        Me.LvDetail.ListItems.Clear

        Call UserForm_Initialize

End Sub

Private Sub CmdSearch_Click()

    On Error Resume Next

    Me.LvDetail.ListItems.Clear

    iTotal = 0

    Dim searchStr As String

    Dim LvItem As ListItem

    iRow = UBound(aData, 2)

    iCol = UBound(aData, 1)

    For i = 0 To iRow

        For j = 0 To iCol

            searchStr = searchStr & "|" & aData(j, i)

        Next

        If InStr(1, searchStr, Me.TextBox1.Value, 1) Then

            Set LvItem = Me.LvDetail.ListItems.Add

            LvItem.Text = aData(0, i)

            For j = 1 To iCol

                LvItem.SubItems(j) = aData(j, i)

            Next

        End If

        searchStr = ""

    Next

End Sub

Private Sub CmdVoucherCopy_Click()

    Usf_VoucherList.Show

End Sub

Private Sub CmdVoucherProcess_Click()

    If VoucherProcType = "凭证制单" Then

        VoucherProcType = "凭证修改"

    Else

        VoucherProcType = "凭证制单"

    End If

    Unload Me

    Usf_AddAndModify.Show

End Sub

Private Sub InkEdit1_DblClick()

    Dim currID As String

    On Error Resume Next

    With Me.LvDetail

        '共同选项

       If .ColumnHeaders(intCol) = "使用状态" Or .ColumnHeaders(intCol) = "状态" Then

            With Usf_Interm

                .Caption = "选择【使用状态】"

                arrType = Array("正常", "封存")

                With Usf_Interm.CmbInterm

                    .Clear

                    .List = arrType

                    .Text = Me.InkEdit1.Text

                End With

                .Show

            End With

        End If

        If currTable = "tb基础信息" Then '基础设置

        ElseIf currTable = "tb用户" Then '用户管理

            If .ColumnHeaders(intCol) = "权限" Then

                With Usf_Interm

                    .Caption = "选择【权限】"

                    '选择用户权限

                    SQL = "select distinct 权限 from tb用户权限"

                    arrType = GetData(dataFile, SQL)

                    With Usf_Interm.CmbInterm

                        .Clear

                        For i = 0 To UBound(arrType, 2)

                            .AddItem arrType(0, i)

                        Next

                        .Text = Me.InkEdit1.Text

                    End With

                    .Show

                End With

            End If

        End If

    End With

End Sub

Private Sub LbTopDate_DblClick(ByVal Cancel As MSForms.ReturnBoolean)

    If Me.TxbDate = "" Then Exit Sub

    preDate = CDate(Me.TxbDate)

    Usf_ChangeDate.Show

End Sub

Private Sub LbTopModify_Click()

If Me.TxbDate = "" Then Exit Sub

Usf_ChangeDate.Show

End Sub

Private Sub TxbDate_Change()

    If VoucherProcType = "凭证修改" Then Exit Sub

    iMonth = Format(Me.TxbDate, "YYYYMM")

    If Format(preDate, "YYYYMM") = iMonth Then Exit Sub

    SQL = "select count(*) from tb凭证 where 月份='" & iMonth & "'"

    n = RecordValue(dataFile, SQL)

    If n > 0 Then

        SQL = "select top 1 凭证号 from tb凭证 where 月份='" & iMonth & "' order by 分录号 DESC"

        preNumber = RecordValue(dataFile, SQL)

        Me.TxbNumber = preNumber + 1

    Else

        Me.TxbNumber = 1

    End If

    'Stop

End Sub

Private Sub LvDetail_Click()

    If currTable = "tb用户" Then

        EditableField = "All"

    End If

    EditableCol = ""

    With Me.LvDetail

        For i = 1 To .ColumnHeaders.Count

            If InStr(EditableField, "All") Then

                If .ColumnHeaders(i) <> "ID" Then

                    EditableCol = EditableCol & Format(i, "00") & "/"

                End If

            ElseIf InStr(EditableField, "Except") Then

                If .ColumnHeaders(i) <> "ID" And InStr(EditableField, .ColumnHeaders(i)) = 0 Then

                    EditableCol = EditableCol & Format(i, "00") & "/"

                End If

            Else

                If InStr(EditableField, .ColumnHeaders(i)) Then

                    EditableCol = EditableCol & Format(i, "00") & "/"

                End If

            End If

        Next

    End With

    If InStr(EditableCol, Format(intCol, "00")) Then

        Call ShowInkEdit

    End If

End Sub

Private Sub TxbNumber_Change()

    If VoucherProcType = "凭证修改" Then Exit Sub

    Me.TxbNumber = Left(Me.TxbNumber, 3)

    Me.TxbNumber = IIf(Val(Me.TxbNumber) = 0, 1, Val(Me.TxbNumber))

End Sub

Private Sub CmdChangeWidth_Click()

    With Me.LvDetail

        For i = 1 To .ColumnHeaders.Count

            W = W + .ColumnHeaders(i).Width

        Next

        .Width = W

        If currTable = "tb凭证" Then

            Me.Width = .Width + 20 + 15

        Else

            Me.Width = .Width + 20

        End If

        W = 0

    End With

    Me.CmdChangeColWidth.Left = Me.LvDetail.Left + Me.LvDetail.Width - Me.CmdChangeColWidth.Width

    Me.CmdChangeWidth.Left = Me.CmdChangeColWidth.Left - Me.CmdChangeWidth.Width - 2

    Me.Frame3.Left = Me.LvDetail.Left + Me.LvDetail.Width - Me.Frame3.Width

    Me.LbTitle.Left = Me.Width / 2 - Me.LbTitle.Width / 2

End Sub

Private Sub UserForm_Initialize()

    dataFile = ThisWorkbook.Path & "\收费管理系统数据库.accdb"

    currTable = "tb用户"

    Dim ItemTypeCode As String

    Dim lbCtrl As Control

    If dataFile = "" Then

        MsgBox "数据库文件路径异常,请重新登录!"

        Exit Sub

    End If

'    Stop

    On Error Resume Next

    'SQL语句,列宽 ,指定可编辑列,必填列的字段名称,标题

    If currTable = "tb用户" Then

'        Stop

        initSQL = "select * from " & currTable & " where 用户ID<>'admin' and 用户ID<>'Superuser'"

        arrWidth = Array(40, 100, 100, 80, 80, 80, 80, 80, 80, 80, 80, 60, 60, 60, 60, 60)

        Me.LbTitle = "用户管理"

        EditableField = "Except/用户ID"

        strRequiredField = "All"

    Else

        initSQL = "select * from " & currTable

        arrWidth = Array(40, 100, 100, 80, 80, 80, 80, 80, 80, 80, 80, 60, 60, 60, 60, 60)

        Me.LbTitle = Right(currTable, Len(currTable) - 2)

        EditableField = "All"

        strRequiredField = "All"

    End If

'    Stop

    '删除动态添加的标签

    For Each lbCtrl In Me.FrmHeader.Controls

        If lbCtrl.Name Like "topLb_*" Then Controls.Remove lbCtrl.Name

    Next

    'Stop

    '添加表头字段,以及标签遮盖层

    Me.Frame1.Top = Me.LbTitle.Top + Me.LbTitle.Height + 5

    tbTitle = GetFields(dataFile, initSQL)

    For i = 0 To UBound(tbTitle, 1)

        With Me.LvDetail

            If i = 0 Then

                .ColumnHeaders.Add , , tbTitle(i), arrWidth(i)

            ElseIf InStr(tbTitle(i), "金额") Or InStr(tbTitle(i), "余额") Then

                .ColumnHeaders.Add , , tbTitle(i), arrWidth(i), lvwColumnRight

            Else

                .ColumnHeaders.Add , , tbTitle(i), arrWidth(i)

            End If

        End With

        Set lbCtrl = Me.FrmHeader.Controls.Add("Forms.Label.1", "topLb_" & i, True)

        If i = 0 Then

            iwidth = 0

        Else

            iwidth = iwidth + arrWidth(i - 1)

        End If

        With lbCtrl

            .Caption = tbTitle(i)

            .Height = 18.5

            .Top = 0

            .Width = arrWidth(i)

            .Left = iwidth

            .BorderStyle = 1

            .FontSize = 10

            .FontName = "微软雅黑"

            .ForeColor = vbWhite 'RGB(50, 50, 255)

            .BackColor = RGB(153, 153, 255)

            .TextAlign = 2

            .ZOrder (0)

        End With

    Next

    'listview控件的显示外观

    With Me.LvDetail

        .View = lvwReport

        .Gridlines = True                        '

        '.Sorted = True

        .CheckBoxes = True

        .LabelEdit = lvwManual

        .FullRowSelect = True

        .ForeColor = vbBlue

        '设置窗体、listview的宽度

        For i = 1 To .ColumnHeaders.Count

            W = W + .ColumnHeaders(i).Width

        Next

        .Width = W

    End With

'    Stop

    '根据指定字段转化可编辑列、必填列

    With Me.LvDetail

        For i = 1 To .ColumnHeaders.Count

            If InStr(EditableField, "All") Then

                If .ColumnHeaders(i) <> "ID" Then

                    EditableCol = EditableCol & Format(i, "00") & "/"

                End If

            ElseIf InStr(EditableField, "Except") Then

                If .ColumnHeaders(i) <> "ID" And InStr(EditableField, .ColumnHeaders(i)) = 0 Then

                    EditableCol = EditableCol & Format(i, "00") & "/"

                End If

            Else

                If InStr(EditableField, .ColumnHeaders(i)) Then

                    EditableCol = EditableCol & Format(i, "00") & "/"

                End If

            End If

            If InStr(strRequiredField, "All") Then '如果是所有列都必填,第一列ID也是不需要且不能编辑的

                If .ColumnHeaders(i) <> "ID" Then

                    strRequiredCol = strRequiredCol & Format(i, "00") & "/"

                End If

            ElseIf InStr(strRequiredField, "Except") Then

                If .ColumnHeaders(i) <> "ID" And InStr(strRequiredField, .ColumnHeaders(i)) = 0 Then

                    strRequiredCol = strRequiredCol & Format(i, "00") & "/"

                End If

            Else

                If InStr(strRequiredField, .ColumnHeaders(i)) Then

                    strRequiredCol = strRequiredCol & Format(i, "00") & "/"

                End If

            End If

        Next

    End With

'    Stop

    If currTable = "tb凭证" Then

        ReDim aData(0 To UBound(tbTitle, 1) - 1, 0 To 5)

        '把金额预填0

        For i = 0 To UBound(aData, 2)

            aData(Pxy(tbTitle, "借方金额") - 1, i) = Format(0, "Standard")

            aData(Pxy(tbTitle, "贷方金额") - 1, i) = Format(0, "Standard")

        Next

    Else

        If RecordValue(dataFile, "select count(*) from " & currTable) > 0 Then

            aData = GetData(dataFile, initSQL)

        End If

    End If

'    Stop

    '添加明细数据到listview

    If Not IsArrEmpty(aData) Then

        iRow = UBound(aData, 2)

        iCol = UBound(aData, 1)

        Me.LvDetail.ListItems.Clear

        For i = 0 To iRow

            Set LvItem = Me.LvDetail.ListItems.Add

            LvItem.Text = aData(0, i)

            ForeColor = IIf(LvItem.index Mod 2, vbBlack, RGB(102, 102, 153))

            LvItem.ForeColor = ForeColor

            For j = 1 To iCol

                LvItem.SubItems(j) = aData(j, i)

                If InStr(EditableCol, Format(j + 1, "00")) Then

                    If LvItem.index Mod 2 Then

                        LvItem.ListSubItems(j).ForeColor = RGB(0, 128, 128)

                    Else

                        LvItem.ListSubItems(j).ForeColor = RGB(51, 204, 204)

                    End If

                Else

                    LvItem.ListSubItems(j).ForeColor = ForeColor

                End If

            Next

        Next

    End If

    '调整控件位置、窗体大小等

    With Me

        .Width = .LvDetail.Width + 20

        .LbTitle.Left = (.Width - .LbTitle.Width) / 2

        .CkB_ChoseFolder.Left = .Width - .CkB_ChoseFolder.Width - 10

        .CmdOutPut.Left = .CkB_ChoseFolder.Left - .CmdOutPut.Width - 10

        .CmdSearch.Left = .CmdOutPut.Left - .CmdSearch.Width - 10

        .TextBox1.Left = .CmdSearch.Left - .TextBox1.Width - 10

        .Frame3.Left = .LvDetail.Left + .LvDetail.Width - .Frame3.Width

    End With

    '对于数据行比较少的表来说,统一的listview控件高度会有很多空行,不太美观,对少于20行的表进行动态调整显示

    n = Me.LvDetail.ListItems.Count

    If n < 20 Then

        If n < 6 Then

            Me.LvDetail.Height = 6 * Me.LvDetail.ListItems(n).Height + 20

        Else

            Me.LvDetail.Height = (n + 1) * Me.LvDetail.ListItems(n).Height + 20

        End If

    Else

        Me.LvDetail.Height = (20 + 1) * Me.LvDetail.ListItems(n).Height + 20

    End If

    'Stop

    With FrmHeader          '表头替代字段,防止Listview表头拖动变化。

        .Visible = True

        .Top = Me.Frame1.Top + Me.Frame1.Height

        .Left = Me.LvDetail.Left

        .Width = Me.LvDetail.Width

        .Height = 19

        .Caption = ""

    End With

    With Me

        .LvDetail.Top = FrmHeader.Top + FrmHeader.Height

        .Height = LvDetail.Height + LvDetail.Top + 80

        .Frame3.Top = .Height - .Frame3.Height - 30

        .CmdChangeColWidth.Top = .FrmHeader.Top - .CmdChangeColWidth.Height

        .CmdChangeColWidth.Left = .FrmHeader.Left + .FrmHeader.Width - .CmdChangeColWidth.Width

        .CmdChangeWidth.Top = .CmdChangeColWidth.Top

        .CmdChangeWidth.Left = .CmdChangeColWidth.Left - .CmdChangeWidth.Width - 2

    End With

    Me.Caption = "【模块:" & Me.LbTitle & "】" _

        & "】【用户:" & currUserName & "】"

    '单独对凭证的显示按钮进行定义

    Me.Frame3.BackColor = Me.BackColor

    '***************************↓使得ListView可编辑相关代码↓*********************************

    preColor = RGB(0, 255, 255)

    InkEdit1.BackColor = preColor

    InkEdit1.Font.size = Me.LvDetail.Font.size

    InkEdit1.Width = 0

    'InkEdit1.MultiLine = False

    InkEdit1.ZOrder 0                            '把InkEdit1移到最上一层,避免被Listview遮住

    sngPixelPerPoint = Pixel2PointX

    blnFlag = True                               '指示InkEdit1_Exit事件是否保存修改。按下Escape键时设为False

    LvmPreWndProc = GetWindowLong(Me.LvDetail.hwnd, GWL_WNDPROC)

    InkPreWndProc = GetWindowLong(InkEdit1.hwnd, GWL_WNDPROC)

    SetWindowLong LvDetail.hwnd, GWL_WNDPROC, AddressOf WndProc

    SetWindowLong InkEdit1.hwnd, GWL_WNDPROC, AddressOf WndProc

    '***************************↑使得ListView可编辑相关代码↑*********************************

End Sub

'***************************↓使得ListView可编辑相关代码↓*********************************

'InkEdit失去焦点时即可发生Exit事件

'InkEdit退出事件。退出时需要指定是否保存修改内容。

Private Sub InkEdit1_Exit(ByVal Cancel As MSForms.ReturnBoolean)

    HideInkEdit blnFlag

    blnFlag = True

End Sub

'InkEdit控件的按键处理程序

Private Sub InkEdit1_KeyUp(pKey As Long, ByVal ShiftKey As Integer)

    Dim lngItemIndex As Long

    Dim lngColCount As Long

    Dim lngItemCount As Long

    Dim LvItem As ListItem

    Dim currIntervals As Single

    If pKey = 27 Then

        intStrikeTimes = intStrikeTimes + 1

        If intStrikeTimes = 1 Then

            lastEscapeTime = Timer

        ElseIf intStrikeTimes = 2 Then

            currIntervals = Timer - lastEscapeTime

        Else

            intStrikeTimes = 0

        End If

    End If

    With LvDetail

        lngItemIndex = .SelectedItem.index

        lngColCount = .ColumnHeaders.Count

        lngItemCount = .ListItems.Count

        blnFlag = True    '原来是放到每一个Case分支里的,这里只是有一条分支是False值

        Select Case pKey

        Case 13                                  '13=回车键

            .SetFocus

            If .ColumnHeaders(intCol) = "贷方金额" Then

                If lngItemIndex < lngItemCount Then

                    Set .SelectedItem = .ListItems(lngItemIndex + 1)

                    intCol = 4   '摘要

                Else

                    Set LvItem = .ListItems.Add

                    LvItem.SubItems(7) = 0: LvItem.SubItems(8) = 0

                    Set .SelectedItem = .ListItems(.ListItems.Count)

                    intCol = 4

                End If

            ElseIf intCol = lngColCount Then

                If lngItemIndex < lngItemCount Then

                    Set .SelectedItem = .ListItems(lngItemIndex + 1)

                    intCol = 2

                Else

                    Set LvItem = .ListItems.Add

                    Set .SelectedItem = .ListItems(.ListItems.Count)

                    intCol = 2

                End If

            Else

                Set .SelectedItem = .ListItems(lngItemIndex)

                intCol = intCol + 1

            End If

            If InStr(EditableCol, Format(intCol, "00")) Then

                .SelectedItem.EnsureVisible

                ShowInkEdit

            End If

        Case 37                                  '37=向左键头

            .SetFocus                            '先触InkEdit1_Exit事件,此后Listview已获焦

            If intCol > 1 Then

                intCol = intCol - 1

                ShowInkEditForLRKey 37

            End If

        Case 38                                  '38=向上键头

            .SetFocus

            If lngItemIndex > 1 Then

                Set .SelectedItem = .ListItems(lngItemIndex - 1)

                .SelectedItem.EnsureVisible

                ShowInkEdit

            End If

        Case 39                                  '39=向右键头

            .SetFocus

            If intCol < lngColCount Then

                intCol = intCol + 1

                ShowInkEditForLRKey 39

            End If

        Case 40                                  '40=向下箭头

            .SetFocus

            If lngItemIndex < lngItemCount Then

                Set .SelectedItem = .ListItems(lngItemIndex + 1)

                .SelectedItem.EnsureVisible

                ShowInkEdit

            End If

        Case 27                                  '27 = Esc键,取消修改

            If intStrikeTimes = 2 Then  '按2次Esc键,并且两次按键时间小于2秒,才退出inkedit,在输入法中会用Esc取消输入

                If currIntervals < 0.8 Then

                    blnFlag = False

                    .SetFocus

                    intStrikeTimes = 0

                End If

            End If

        Case Else

        End Select

    End With

End Sub

'把X方向的像素值转为磅。VBA窗体的度量单位是磅。

'像素和磅的转换跟屏幕密度有关,不同电脑可能不同值。

Private Function Pixel2PointX() As Double

    Dim hDC As Long, DPIx As Long

    hDC = GetDC(0)                               '获取屏幕设备环境句柄

    DPIx = GetDeviceCaps(hDC, LOGPIXELSX)        '获取屏幕X方向像素密度

    ReleaseDC 0, hDC                             '释放屏幕设备环境

    Pixel2PointX = 72 / DPIx

End Function

'鼠标事件主要计算点击的列号。并可在此处鼠标按键条件,比如改为右键点击才计算列号,左键时列号置为零。这样InkEdit的显示程序就不会显示控件

Private Sub LvDetail_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As stdole.OLE_XPOS_PIXELS, ByVal Y As stdole.OLE_YPOS_PIXELS)

    Dim sngDiff As Double                        '单击鼠标,弹起时即可触发事件。可用Button判断点击的是鼠标三键中的哪一个,1=左,2=右,4=中

    Dim sngScrollPos As Double

    Dim sngMousePosX As Double

    With LvDetail

        sngScrollPos = sngPixelPerPoint * GetScrollPos(.hwnd, SB_HORZ)

        sngMousePosX = sngPixelPerPoint * X

        For intCol = 1 To .ColumnHeaders.Count

            sngDiff = .ColumnHeaders(intCol).Left - sngScrollPos

            If sngMousePosX > sngDiff And sngMousePosX < sngDiff + .ColumnHeaders(intCol).Width Then Exit For

        Next

        If intCol > .ColumnHeaders.Count Then intCol = 0 '计算失败时,置为零

    End With

End Sub

'InkEdit控件退出时的处理程序,将修改内容同步到Listview

Private Sub HideInkEdit(Optional ByVal blnSave As Boolean = True)

    Dim OldFullName$, NewFullName$

    Dim myID As Integer                          '当前修改的ID

    On Error Resume Next

    InkEdit1.BackColor = preColor

    With LvDetail

        If .SelectedItem Is Nothing Then Exit Sub '如果InkEdit1未失焦时就关闭窗体,必报错。必须加这一句。

        If strOriginal = InkEdit1.Text Then InkEdit1.Width = 0: Exit Sub 'InkEdit的值有改变时才执行后面语句,否则浪费时间

        If Len(strRequiredCol) Then

            If InStr(strRequiredCol, Format(intCol, "00")) Then

                If Len(InkEdit1.Text) = 0 Then

                    MsgBox "该项为必填项,修改已被取消!", vbCritical

                    InkEdit1.Width = 0: Exit Sub

                End If

            End If

        End If

        If blnSave Then

            If intCol > 1 Then

               '1用户管理

                If currTable = "tb用户" Then

                    If .ColumnHeaders(intCol) = "用户ID" Then

                        If RecordValue(dataFile, "select count(用户ID)  From tb用户 where 用户ID='" & InkEdit1.Text & "'") > 0 Then

                            MsgBox "已存在【" & InkEdit1.Text & "】用户ID不能重复!"

                            Me.InkEdit1.Text = ""

                            Exit Sub

                        End If

                        If Len(InkEdit1.Text) < 4 Then

                            MsgBox "用户ID不能低于4位"

                            InkEdit1.Text = ""

                            Exit Sub

                        End If

                    ElseIf .ColumnHeaders(intCol) = "姓名" Then

                        If RecordValue(dataFile, "select count(姓名)  From tb用户 where 姓名='" & InkEdit1.Text & "'") > 0 Then

                            MsgBox "已存在【" & InkEdit1.Text & "】姓名不能重复!"

                            Me.InkEdit1.Text = ""

                            Exit Sub

                        End If

                        If Len(InkEdit1.Text) < 2 Then

                            MsgBox "姓名至少2个字符"

                            InkEdit1.Text = ""

                            Exit Sub

                        End If

                    ElseIf .ColumnHeaders(intCol) = "密码" Then

                        If Len(InkEdit1.Text) < 6 Then

                            MsgBox "密码不能低于6位"

                            InkEdit1.Text = ""

                            Exit Sub

                        End If

                    End If

                    .SelectedItem.SubItems(intCol - 1) = InkEdit1.Text

                    If .SelectedItem.Text = "" Then

                        .SelectedItem.SubItems(Pxy(tbTitle, "状态") - 1) = "正常"

                    End If

                Else                             '对应 类似 ElseIf currtable="tb?" Then

                    .SelectedItem.SubItems(intCol - 1) = InkEdit1.Text

                End If

            Else                                 '对应 if incol>1

                .SelectedItem.Text = InkEdit1.Text

            End If

            If .SelectedItem.Text = "" Then

                .SelectedItem.ListSubItems(intCol - 1).ForeColor = vbBlue '新增的记录标蓝

            Else

                .SelectedItem.ListSubItems(intCol - 1).ForeColor = vbRed '修改的记录标红

            End If

            ModifyStatus = ModifyStatus + 1

            '将生产修改的记录的ID添加到strModifiedID中,两边用/隔开,做到精确匹配

            myID = Val(.SelectedItem.Text)

            If myID > 0 Then

                If InStr(strModifiedID, "/" & myID & "/") = 0 Then

                    strModifiedID = strModifiedID & "/" & myID & "/"

                End If

            End If

            '**********将生产涉及修改的其他核算项目记录的ID写入数组保存***********

        End If

    End With

    InkEdit1.Width = 0

End Sub

Private Sub tb报表项目Process()

End Sub

'左右方向键处理程序。主要计算是水平滚动条的滚动量,以确保InkEdit可见

Private Sub ShowInkEditForLRKey(ByVal intKey As Integer)

    Dim sngNewInkLeft As Double

    Dim lngScrollAmount As Long

    Dim blnInkLocked As Boolean

    With LvDetail

        If intCol = 0 Then Exit Sub

        If .SelectedItem Is Nothing Then Exit Sub

        If InStr(EditableCol, Format(intCol, "00")) = 0 Then Exit Sub

        If intCol > 1 Then

            InkEdit1.Text = .SelectedItem.SubItems(intCol - 1)

        Else

            InkEdit1.Text = .SelectedItem.Text

        End If

        If intKey = 37 Then                      '向左

            sngNewInkLeft = InkEdit1.Left - .ColumnHeaders(intCol).Width

            If sngNewInkLeft < .Left + 1.5 Then

                lngScrollAmount = CLng((sngNewInkLeft - (.Left + 1.5)) / sngPixelPerPoint) '滚动量,单位像素

                SendMessageLong .hwnd, LVM_SCROLL, lngScrollAmount, 0 '拖动Listview水平滚动条,保持InkEdit可见

                InkEdit1.Left = .Left + 1.5

            Else

                InkEdit1.Left = sngNewInkLeft

            End If

        Else                                     '向右

            sngNewInkLeft = InkEdit1.Left + .ColumnHeaders(intCol - 1).Width

            If sngNewInkLeft + .ColumnHeaders(intCol).Width > .Left + .Width Then

                lngScrollAmount = CLng((sngNewInkLeft + .ColumnHeaders(intCol).Width - (.Left + .Width)) / sngPixelPerPoint)

                SendMessageLong .hwnd, LVM_SCROLL, lngScrollAmount, 0

                InkEdit1.Left = .Left + .Width - .ColumnHeaders(intCol).Width

            Else

                InkEdit1.Left = sngNewInkLeft

            End If

        End If

        InkEdit1.Top = .Top + .SelectedItem.Top + 1.5

        InkEdit1.Width = .ColumnHeaders(intCol).Width

        InkEdit1.Height = .SelectedItem.Height

        If Len(EditableCol) Then

            blnInkLocked = (InStr(EditableCol, Format(intCol, "00")) = 0)

        Else

            blnInkLocked = False

        End If

        InkEdit1.Locked = blnInkLocked

        InkEdit1.SelStart = 0

        InkEdit1.SelLength = Len(InkEdit1.Text)

        strOriginal = InkEdit1.Text

        InkEdit1.SetFocus

    End With

End Sub

'显示InkEdit控件的处理程序。需要显示InkEdit时调用

Private Sub ShowInkEdit()

    Dim sngScrollPos As Double

    Dim blnInkLocked As Boolean

    Dim iItem As String

    With LvDetail

        If intCol = 0 Then Exit Sub              '点击的列号未计算成功

        If .SelectedItem Is Nothing Then Exit Sub 'Listview列表为空时退出

        sngScrollPos = sngPixelPerPoint * GetScrollPos(.hwnd, SB_HORZ)

        If intCol > 1 Then

            InkEdit1.Text = .SelectedItem.SubItems(intCol - 1)

            strOriginal = InkEdit1.Text

            intRow = .SelectedItem.index

        Else

            InkEdit1.Text = .SelectedItem.Text

        End If

        InkEdit1.Left = .ColumnHeaders(intCol).Left + .Left + 1.5 - sngScrollPos

        InkEdit1.Top = .Top + .SelectedItem.Top + 1.5

        InkEdit1.Width = .ColumnHeaders(intCol).Width

        InkEdit1.Height = .SelectedItem.Height

        If Len(EditableCol) Then

            blnInkLocked = (InStr(EditableCol, Format(intCol, "00")) = 0)

        Else

            blnInkLocked = False

        End If

        InkEdit1.Locked = blnInkLocked

        InkEdit1.SelStart = 0

        InkEdit1.SelLength = Len(InkEdit1.Text)

        'strOriginal = InkEdit1.Text   '移到前面

        InkEdit1.SetFocus

    End With

End Sub

'关闭窗体时,还原Listview和InkEdit控件的窗口程序,在退出窗体时调用

Private Sub RestoreAPI()

    SetWindowLong LvDetail.hwnd, GWL_WNDPROC, LvmPreWndProc

    SetWindowLong InkEdit1.hwnd, GWL_WNDPROC, InkPreWndProc

End Sub

'***************************↑使得ListView可编辑相关代码↑*********************************

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)

    If CloseMode = vbFormControlMenu Then '检测关闭模式是否为点击窗口右上角的 X

        Cancel = True '取消关闭事件

    End If

End Sub

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多