Modify account expiry date based on data from Excel - excel

I need to modify the expiry date on Active Directory user accounts, taking the account name and date to set from data that is in Excel.
I have the below VBScript to set an AD expiry date, but I can't work out how to change it so that it takes the account name and date to set as the expiry from particular cells in Excel.
The aim is to provide easy bulk administration of this task that we have to do daily.
Set objUser = GetObject _
("LDAP://cn=Joe.Bloggs,ou=Management,dc=AN,dc=Franz,dc=com")
objUser.AccountExpirationDate = "10/30/2014"
objUser.SetInfo

Your sample code requires a distinguished name, so you need to resolve the account name to the user object's distinguished name:
acct = "..." 'account name
Set rootDSE = GetObject("LDAP://rootDSE")
base = "<LDAP://" & rootDSE.Get("DefaultNamingContext") & ">"
filter = "(&(objectClass=user)(objectCategory=person)(sAMAccountName=" _
& acct & "))"
attr = "distinguishedName"
scope = "subtree"
Set conn = CreateObject("ADODB.Connection")
conn.Provider = "ADsDSOObject"
conn.Open "Active Directory Provider"
Set cmd = CreateObject("ADODB.Command")
Set cmd.ActiveConnection = conn
cmd.CommandText = base & ";" & filter & ";" & attr & ";" & scope
Set rs = cmd.Execute
Do Until rs.EOF
dn = rs.Fields("distinguishedName").Value
rs.MoveNext
Loop
WScript.Echo dn
Since AD queries require quite a bit of boilerplate code, and I got tired of having to write it over and over again, I wrapped it in a reusable VBScript class (ADQuery). With this class you can simplify the query to the following:
'<-- copy/paste class code here
acct = "..." 'account name
Set qry = New ADQuery
qry.Filter = "(&(objectClass=user)(objectCategory=person)(sAMAccountName=" _
& acct & "))"
Set rs = qry.Execute
Do Until rs.EOF
dn = rs.Fields("distinguishedName").Value
rs.MoveNext
Loop
WScript.Echo dn
Replace the distinguished name in the code you copied from ActiveXperts with the variable dn:
objUser = GetObject("LDAP://" & dn)
objUser.AccountExpirationDate = "10/30/2014"
objUser.SetInfo
The account names can be read from an Excel sheet with something like this (provided you have Excel installed):
Set xl = CreateObject("Excel.Application")
Set wb = xl.Workbooks.Open("C:\path\to\your.xlsx")
Set range = wb.Sheets(1).UsedRange
For i = range.Rows(1).Row To range.Rows(range.Rows.Count).Row
acct = range.Cells(i, 1).Value
'rest of your code here
Next
wb.Close
xl.Quit

Related

Excel VBA - Workaround LDAP administrative limits

In a UserForm I've got multiple listboxes.
A list of all Groups in the Active Directory (AD);
A list of selected Groups from ListBox1;
A list of unique members (hence the use of a dictionary since some users can be a member of multiple groups) of these selected groups;
I'm at the point where the first and second lists work fine, however I'm hitting the LDAP administrative limit when the query will return over 1000 records which will return a run-time error 'error -2147016669'. It's this exact problem for reference. Anything below a 1000 and the code will run smooth.
I'm moving in unfamiliar territory and I'm unable to find the correct way to implement the "Page Size" property so that the full list of users will populate the initialized dictionary:
Private Sub Button1_Click()
Set rootDSE = GetObject("LDAP://rootDSE")
domainDN = rootDSE.Get("defaultNamingContext")
Set ado = CreateObject("ADODB.Connection")
ado.Provider = "ADSDSOObject"
ado.Open "ADSearch"
Set Dict_members = CreateObject("Scripting.Dictionary")
For n = 0 To ListBox2.ListCount - 1
If Me.ListBox2.Selected(n) = True Then
ldapFilter = "(sAMAccountName=" & Me.ListBox2.List(n) & ")"
Set objectList = ado.Execute("<LDAP://" & domainDN & ">;" & ldapFilter & ";distinguishedName,primaryGroupToken;subtree")
groupDN = objectList.Fields("distinguishedName")
groupRID = objectList.Fields("primaryGroupToken")
ldapFilter = "(|(memberOf=" & groupDN & ")(primaryGroupID=" & groupRID & "))"
Set objectList = ado.Execute("<LDAP://" & domainDN & ">;" & ldapFilter & ";distinguishedName,samAccountName,displayname,userPrincipalName;subtree")
While Not objectList.EOF
On Error Resume Next
If Not IsNull(objectList.Fields("userPrincipalName")) Then
Dict_members(objectList.Fields("userPrincipalName").Value) = 1
End If
'logonNameUPN = objectList.Fields("userPrincipalName")
On Error GoTo 0
objectList.MoveNext
Wend
objectList.Close
End If
Next
ado.Close
Me.ListBox3.List = Dict_members.Keys
Me.Label6.Caption = Dict_members.Count
End Sub
I guess the idea is to 'loop' in batches of 1000. Any help is appreciated.
I got it working now; granted I don't know exactly why:
Private Sub Label5_Click()
Set rootDSE = GetObject("LDAP://rootDSE")
domainDN = rootDSE.Get("defaultNamingContext")
Set ado = CreateObject("ADODB.Connection")
ado.Open "Provider=ADsDSOObject;"
Set AdoCmd = CreateObject("ADODB.Command")
AdoCmd.ActiveConnection = ado
AdoCmd.Properties("Page Size") = 1000
Set Dict_members = CreateObject("Scripting.Dictionary")
For n = 0 To ListBox2.ListCount - 1
If Me.ListBox2.Selected(n) = True Then
ldapFilter = "(sAMAccountName=" & Me.ListBox2.List(n) & ")"
AdoCmd.CommandText = "<LDAP://" & domainDN & ">;" & ldapFilter & ";distinguishedName,primaryGroupToken;subtree"
Set objectList = AdoCmd.Execute
groupDN = objectList.Fields("distinguishedName")
groupRID = objectList.Fields("primaryGroupToken")
ldapFilter = "(|(memberOf=" & groupDN & ")(primaryGroupID=" & groupRID & "))"
AdoCmd.CommandText = "<LDAP://" & domainDN & ">;" & ldapFilter & ";distinguishedName,samAccountName,displayname,userPrincipalName;subtree"
Set objectList = AdoCmd.Execute
While Not objectList.EOF
On Error Resume Next
If Not IsNull(objectList.Fields("userPrincipalName")) Then
Dict_members(objectList.Fields("userPrincipalName").Value) = 1
End If
On Error GoTo 0
objectList.MoveNext
Wend
objectList.Close
End If
Next
ado.Close
Me.ListBox3.List = Dict_members.Keys
Me.Label6.Caption = Dict_members.Count
End Sub
So what is different to the code I initially had used is:
ado.Open "Provider=ADsDSOObject;" instead of ado.Open "ADSearch";
The 'ADODB.Command' to be able to use and set properties. In order to execute properly I also had to initialize the AdoCmd.CommandText, and then execute.
For some reason a more direct:
Set objectList = AdoCmd.Execute("<LDAP://" & domainDN & ">;" & ldapFilter & ";distinguishedName,primaryGroupToken;subtree")
Would yield an error.
This is the result of some trial and error, but it works flawlessly now and will return thousands and thousands of users if need be.
You may be working too hard with this code. If it were me, I'd pull back all the columns I wanted from Active Directory using Power Query and then just use normal Excel table and Pivot operations.
Data > Get Data > From Other Sources > From Active Directory

VBA passing multiple parameters to SQL through functions

I have been struggling with this code. I can get the desired result if Iam only passing one parameter, however as soon as I try and pass two I get value error.
for example the parameters I need to pass is for period 202110 AccountCode 412 both are type long.
I set my Rs to execute as such:
Set rs = conn.Execute("SELECT SUM(ActualAmountOrgCurrency) AS AmountOrg FROM Vba_ProfitandLoss WHERE FinPeriod = AND AccountCodeShort = " & Period & Account)
This returns a value error in excel but if I choose only one parameter it returns fine.
full code is here;
Public Function AmountOrgCurrency(Period As Long, Account As Long)
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim strConnString As String
strConnString = "Provider=SQLOLEDB;Data Source=sql2016ch01;" _
& "Initial Catalog=ODS;Integrated Security=SSPI;"
Set conn = New ADODB.Connection
conn.Open strConnString
Set rs = conn.Execute("SELECT SUM(ActualAmountOrgCurrency) AS AmountOrg FROM Vba_ProfitandLoss WHERE FinPeriod = AND AccountCodeShort = " & Period & Account)
If Not IsNumeric(rs.Fields("AmountOrg").Value) Then
AmountOrgCurrency = 0
Else
AmountOrgCurrency = rs.Fields("AmountOrg").Value
rs.Close
End If
End Function
Set rs = conn.Execute("SELECT SUM(ActualAmountOrgCurrency) AS AmountOrg " & _
" FROM Vba_ProfitandLoss WHERE FinPeriod = " & Period & _
" AND AccountCodeShort = " & Account)
You need to build a string which is valid SQL - while debugging it's useful to Debug.Print the final SQL to check it for correctness.

When searching an Access database from an Excel userform is it possible to search other columns than just the ID column?

I would like to search the access database with the user initials in the UserInitials column but I get the error no value given for one or more required parameters
However, if I search the database with the ID in the ID column it works perfectly fine.
Is it possible to do this? I have checked the spelling which is fine and there are no empty fields in the database itself. I have also changed and set the Primary key from ID to UserInitials but this doesn't seem to make any difference.
Many thanks.
Public Function searchDatabase()
If UserForm1.TextBox4.Value = "" Then
MsgBox "field empty"
Else
Dim con As New ADODB.Connection
Dim rs As New ADODB.Recordset
con.connectionstring = "Provider=Microsoft.ACE.OLEDB.12.0;Data
Source=C:\Users\MyPC\Desktop\DatabaseOne.accdb;"
'Open Db connection
con.Open
Set rs.ActiveConnection = con
rs.Open "Select * from TableUser where UserInitials= " & UserForm1.TextBox4.Text & ""
StartRow = 3
Do Until rs.EOF
'User Initials
UserForm1.TextBox1.Text = rs.Fields(1).Value
'User Full Name
UserForm1.TextBox2.Text = rs.Fields(2).Value
'User Email
UserForm1.TextBox3.Text = rs.Fields(3).Value
rs.MoveNext
StartRow = StartRow + 1
Loop
Set rs = Nothing
con.Close
Set con = Nothing
End If
End Function
You need to embed UserForm1.TextBox4.Text in quotation marks otherwise the SQL statement will not be interpreted correctly
Try
rs.open "Select * from TableUser where UserInitials= '" & UserForm1.TextBox4.Text & "'"
Further reading Quotation marks in string expressions

windows script host error (Error Code 8007202f)

An error occurred while using a custom VBScript to create users in active directory users and computers in windows server 2012.
Error Code 8007202f, a Constraint Violation occurred
The .vbs file retrieves data from an Excel file. I used the script to create user accounts once, but when the script was used again for the second time, the error occurred.
Here is the script I used:
'On Error Resume Next
'Make sure to change the OU name as appropriate. Watch about the space after the name.
'Change the domain name also
strOU = "OU=TempOU ,"
strSheet = "C:\staff.xls"
'strPWD = "12345678"
' Bind to Active Directory, Users container.
Set objRootLDAP = GetObject("LDAP://rootDSE")
Set objContainer = GetObject("LDAP://" & strOU & _
objRootLDAP.Get("defaultNamingContext"))
' Open the Excel spreadsheet
Set objExcel = CreateObject("Excel.Application")
Set objSpread = objExcel.Workbooks.Open(strSheet)
intRow = 2 'Skip row for headings
Do Until objExcel.Cells(intRow,1).Value = ""
strCN = Trim(objExcel.Cells(intRow, 1).Value)
strFirst = Trim(objExcel.Cells(intRow, 2).Value)
strSam = Trim(objExcel.Cells(intRow, 3).Value)
strDscpt = Trim(objExcel.Cells(intRow, 4).Value)
strLast = Trim(objExcel.Cells(intRow, 5).Value)
strpasswd=Trim(objExcel.Cells(intRow, 6).Value)
'strpasswd=""
'Principal Name
strPrin = strSam & "#" & "NSBMTEST.com"
'New Container Name and display
strCNnew = strCN
'Created container name as SMB_
Set objUser = objContainer.Create("User", "cn=" & strCNnew)
objUser.userPrincipalName = strPrin
objUser.sAMAccountName = strSam
objUser.givenName = strFirst
'objUser.sn = strLast
objUser.displayName = strCNnew
objUser.Description = strDscpt
objUser.SetInfo
' enable account with password
objUser.userAccountControl = 512
objUser.pwdLastSet = 0
objUser.SetPassword strPWD
objUser.SetPassword strpasswd
objUser.SetInfo
'Pw set to not expire
'Const ADS_UF_DONT_EXPIRE_PASSWD = &H10000
'lngFlag = objUser.userAccountControl
' lngFlag = lngFlag Or ADS_UF_DONT_EXPIRE_PASSWD
'objUser.userAccountControl = lngFlag
'objUser.SetInfo
intRow = intRow + 1
Loop
objExcel.Quit
WScript.Quit

how to read data from excel sheet and store it into a user defined variable

I have created a code to modify a date by adding specific no of days into it by using a variable name Date.
Now i am having several texts including several different dates in excel sheet which i want to read then modify and again rewrite into same excel sheet.
For this i have created a code but i am not able to load the data read from excel sheet to a variable.
please suggest and provide a code/query how to read data from excel sheet and store it into a user defined variable
Try this example
values are stored in rowData variable
Set objExcel = CreateObject("Excel.Application")
Set objWorkbook = objExcel.Workbooks.Open("D:\VBScriptTrainee\Teams.xlsx")
objExcel.visible=True
rowCount=objExcel.ActiveWorkbook.Sheets(1).UsedRange.Rows.count
colCount=objExcel.ActiveWorkbook.Sheets(1).UsedRange.Columns.count
Msgbox("Number of Rows are " & rowCount)
Msgbox("Number of columns are " & colCount)
intRow = 1
intCol = 1
rowData=null
for intRow=1 to rowCount step 1
for intCol=1 to colCount step 1
rowData = rowData & " " & objExcel.Cells(intRow, intCol).Value
next
rowData = rowData & vbnewline
next
Msgbox(rowData)
objExcel.Quit
set objExcel=nothing
If you have dates in excel in the single column with column name as
're-data'. We can take out sample code using ADO connection string. Here is the sample VBS code.
filelocation = "D:\New Microsoft Excel Worksheet.xlsx"
SheetName = "Sheet1"
column_name = "re_data"
row_number = 8
'Create connection
Set conn = CreateObject("ADODB.Connection")
'Create Record Set
Set recordset = CreateObject("ADODB.Recordset")
'Connection String
conn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & filelocation & ";Extended Properties = Excel 12.0 Macro;"
On Error Resume Next
'Connection Open
conn.Open
query = "SELECT * FROM " & "[" & SheetName & "$] "
recordset.Open query, conn, 3, 3
Count = 1
Do Until recordset.EOF Or Count = row_number
Output_variable = recordset.Fields.Item(column_name).Value
recordset.MoveNext
Count = Count + 1
Loop
MsgBox Output_variable
recordset.Close
conn.Close

Resources