简体   繁体   中英

How to unlock and lock Excel cells for running a macro

I have a spreadsheet that has two buttons - To retrieve records from database and another one to upload changes from excel to database. The macro for retrieving records from Database is as follows. Now after retrieving the records, I want the users only to edit certain columns( here the columns from January to Scenario) so that the users, after updating those cells can click on the update button to save the changes to the database. However, I don't want them to touch the other columns ( EmpID through Status).I want a macro that would lock those columns after data retrieval and unlock while retrieving the records on clicking the Retrieval button. This is because I am clearing the worksheet whenever I click on the retrieve records buttons. I tried several methods and it's not working. I would appreciate your help.

Public Sub RetrieveDBToWorkSheet()
Dim sQry As String
Dim iRows As Integer
Dim iCols As Integer
Dim SQL As String



On Error GoTo ErrHandler



'Clear worksheet
Call ClearExistingRows(4)

'Create ADODB Recordset for retrieved data
Call DBConnection.OpenDBConnection

'Create Recordset
Dim rsMY_Resources As ADODB.Recordset
Set rsMY_Resources = New ADODB.Recordset

SQL = "SELECT  EmpID, EName, CCNum, CCName, ProgramNum, ProgramName, ResTypeNum, ResName, Status, January, February, March, April, May, June, July, August, September, October, November, December, Total_Year, Year, Scenario from Actual_FTE2"

'Query the database

rsMY_Resources.Open SQL, DBConnection.oConn, adOpenStatic, adLockReadOnly
If rsMY_Resources.EOF = True Then
    MsgBox ("No record found in database")
    Exit Sub
End If

'Fill excel active sheet, starting from row# 3
iRows = 3
For iCols = 0 To rsMY_Resources.Fields.Count - 1
    ActiveSheet.Cells(iRows, iCols + 1).Value = rsMY_Resources.Fields(iCols).Name
Next
ActiveSheet.Range(ActiveSheet.Cells(iRows, 1), ActiveSheet.Cells(iRows, rsMY_Resources.Fields.Count)).Font.Bold = True

iRows = iRows + 1
ActiveSheet.Range("A" + CStr(iRows)).CopyFromRecordset rsMY_Resources

iRows = rsMY_Resources.RecordCount

'Clean up
rsMY_Resources.Close:
Set rsMY_Resources = Nothing

Call DBConnection.CloseDBConnection


MsgBox (CStr(iRows) + " records have been retrieved from the database!")


Exit Sub

ErrHandler:
MsgBox (Error)

End Sub

Public Sub ClearExistingRows(lRowStart As Long)
Dim lLastRow As Long
Dim iLastCol As Integer

 If (Not (Cells.Find("*", Range("A1"), xlFormulas, , xlByRows, xlPrevious) 
 Is Nothing)) Then
    lLastRow = Cells.Find("*", Range("A1"), xlFormulas, , 
   xlByRows,xlPrevious).Row ' Find the last row with data

    If (lLastRow >= lRowStart) Then
        iLastCol = Cells.Find("*", Range("A1"), xlFormulas, , xlByColumns, 
    xlPrevious).Column ' Find the last column with data
        Range(Cells(lRowStart, 1), Cells(lLastRow, iLastCol)).Select
        Selection.EntireRow.Delete
       End If
    End If
   End Sub

Thanks, Hema

One of the best ways to learn how to do something in VBA is simply to perform the task with the Macro Recorder on. That way you will know the basic code required to complete the task.

It also helps to understand that all cells start off with a property of "Locked" but that only becomes useful when the workbook is Protected using the Review > Protect Sheet option.

So to make sure no one can change all any of the cells in your book after the data has been changed, you'd need to protect the workbook using:

ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True

The various options could be changed or removed depending on what you want done.

As I understand it, you want only certain columns locked. In this case, you actually have to unlock the cells you will allow them to enter - so you have to think about it backwards.

This line of code would set the Locked property of the cells C1:C1000 to False so that when the Workbook is Protected, the user can still edit the cells:

Range("C1:C1000").Locked = False

If you have any other questions, just post.

Refer to the Microsoft Documentation here: https://msdn.microsoft.com/en-us/VBA/excel-vba/articles/range-locked-property-excel

After your:

MsgBox (CStr(iRows) + " records have been retrieved from the database!")

Place this code:

Dim rngCol As Range ' Create a Range object

Set rngCol = ActiveSheet.Range("A:Z") ' Select all columns on sheet
   rngCol.Locked = False              ' Unlock all columns
Set rngCol = ActiveSheet.Range("A:I") ' Now Select columns EmpID - Status
   rngCol.Locked = True               ' Lock only those columns
   ActiveSheet.Protect                ' Protect will now only protect the Locked columns

When you enter the procedure where you need to rewrite everything:

Public Sub RetrieveDBToWorkSheet()

Place this code to unlock the whole sheet:

ActiveSheet.Unprotect  ' This will unprotect the whole sheet

You have to remember to unlock all the columns on the sheet first. If you don't, then the protect will lock down all of your columns (even though you specifically "locked" the range you want). This is unintuitive and has baffled many excel users.

Have you already tried activesheet.protect?

At the beginning of the script you would have to add the following to "unprotect" the sheet to work with.

    activesheet.unprotect

Then the script is run. At the end of your sub first define the columns which you want your user to be able to change: (As an example Colum B)

    Columns("B:B").Select 
    Selection.Locked = False

following that, protect the sheet

    activesheet.protect

I think it should work.

I manage to unprotect a Microsoft Excel 97-2003 Worksheet (.xls) following the next steps

  1. Open the file
  2. Allow editing and macros
  3. Click ALT + F11
  4. Place the following code

    Sub UnprotectSheet() Dim i, i1, i2, i3, i4, i5, i6 As Integer, j As Integer, k As Integer, l As Integer, m As Integer, n As Integer On Error Resume Next For i = 65 To 66 For j = 65 To 66 For k = 65 To 66 For l = 65 To 66 For m = 65 To 66 For i1 = 65 To 66 For i2 = 65 To 66 For i3 = 65 To 66 For i4 = 65 To 66 For i5 = 65 To 66 For i6 = 65 To 66 For n = 32 To 126 ActiveSheet.Unprotect Chr(i) & Chr(j) & Chr(k) & Chr(l) & Chr(m) & Chr(i1) & Chr(i2) & Chr(i3) & Chr(i4) & Chr(i5) & Chr(i6) & Chr(n) If ActiveSheet.ProtectContents = False Then MsgBox "One usable password is " & Chr(i) & Chr(j) & _ Chr(k) & Chr(l) & Chr(m) & Chr(i1) & Chr(i2) & _ Chr(i3) & Chr(i4) & Chr(i5) & Chr(i6) & Chr(n) Exit Sub End If Next Next Next Next Next Next Next Next Next Next Next Next End Sub
  5. Click ALT + F11 to go back to the sheet.

  6. Click ALT + F8 to go to Macro.
  7. Run the UnprotectSheet created previously.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM