Related
I am trying to obtain the manager of the user found in AD using Excel VBA. The code is as follows:
Sub ADQuery()
MsgBox GetDepartment("Simpson", "Homer")
End Sub
Function GetDepartment(strLastName As String, strFirstName As String) As String
Dim objRoot As Object
Dim strDomain As String
Dim objConn As Object
Dim objComm As Object
Dim objRecordset As Object
Dim sFilter As String
Dim sAttribs As String
Dim sDepth As String
Dim sBase As String
Dim sQuery As String
Set objRoot = GetObject("LDAP://RootDSE")
strDomain = objRoot.Get("DefaultNamingContext")
Set objConn = CreateObject("ADODB.Connection")
Set objComm = CreateObject("ADODB.Command")
strLastName = Replace(strLastName, Space(1), "")
strFirstName = Replace(strFirstName, Space(1), "")
sFilter = "(&(objectClass=person)(objectCategory=user)(givenName=" & strFirstName & ")" & "(sn=" & strLastName & "*)" & ")"
sAttribs = "manager,sAMAccountName,givenName,sn"
sDepth = "SubTree"
sBase = "<LDAP://" & strDomain & ">"
sQuery = sBase & ";" & sFilter & ";" & sAttribs & ";" & sDepth
objConn.Open "Data Source=Active Directory Provider;Provider=ADsDSOObject"
Set objComm.ActiveConnection = objConn
objComm.Properties("Page Size") = 40000
objComm.CommandText = sQuery
Set objRecordset = objComm.Execute
Do Until objRecordset.EOF
GetDepartment = objRecordset("department")
Exit Function
objRecordset.MoveNext
Loop
End Function
But I get the following error message:
Run-time error '3265': Item cannot be found in the collection corresponding to the requested name or ordinal.
Looking in AD itself, it seems the 'manager' attribute listed in the Attribute Editor is listed with a value:
CN=Burns\, Montgomery,OU=Users,OU=Springfield,OU=Nuclear Power Plant,DC=powerplantnet,DC=com
And the syntax is Distinguished Name.
My function returns a string and I can see that the manager attribute is not a string. How do I get the information back as a string?
I found some code on the internet and tinkered with it to list all the members of a group in Active Directory.
my final result must be similar to this:
E.g.
Group 1, User 1
Group 1, User 2
Group 2, User 1
Group 3, User 3
Etc
Function GetGroupUsers(ByVal strGroupName As String) As String
Dim objGroup, objDomain, objMember
Dim strMemberlist As String, strDomain As String
Set objDomain = GetObject("LDAP://rootDse")
strDomain = objDomain.Get("dnsHostName")
Debug.Print strGroupName
Debug.Print strDomain
Set objGroup = GetObject("WinNT://" & strDomain & "/" & strGroupName & ",group")
Debug.Print objGroup
Dim i
i = 0
For Each objMember In objGroup.Members
strMemberlist = strMemberlist & "," & objMember.Name
Debug.Print strMemberlist
i = i + 1
Debug.Print i
Next objMember
' strip off the leading comma
GetGroupUsers = Mid$(strMemberlist, 2)
End Function
Each member can have couple of groups
try look around this
Sub testLookup()
PrintMemberOf Environ("USERNAME")
End Sub
Public Sub PrintMemberOf(samAccountName As String)
Dim sDomain As String
Dim groups As Variant
Dim x As Long
'Get the Domain from the Current logged on user
Set dd = CreateObject("ADSystemInfo")
With CreateObject("ADSystemInfo")
sDomain = .DomainShortName
End With
'Assign the groups to an array
groups = GetMembers(GetDN(samAccountName, sDomain))
'Print each group
For x = LBound(groups) To UBound(groups)
Debug.Print groups(x)
Next x
End Sub
Public Function GetMembers(strDN As String) As Variant
'Function to return the memberof property
With GetObject("LDAP://" & strDN)
GetMembers = .memberOf
End With
End Function
Function GetDN(ByVal samAccountName, ByVal sDomain)
'Function to return the DN from a given samAccountName and Domain
With CreateObject("NameTranslate")
.Init 1, sDomain
.Set 3, sDomain & "\" & samAccountName
GetDN = .Get(1)
End With
End Function
Function getADAll()
UserName = Environ("USERNAME")
Set RootDSE = GetObject("LDAP://RootDSE")
Base = "<LDAP://" & RootDSE.Get("defaultNamingContext") & ">"
'filter on user objects with the given account name
'"samAccountName,givenName,sn,displayName,mail,userPrincipalName,l,c,mobile,facsimileTelephoneNumber,info,title,department,company,manager"
attr = "samAccountName,givenName,sn,displayName,mail,userPrincipalName,l,c,mobile,facsimileTelephoneNumber,info,title,department,company,manager"
fltr = "(&(objectClass=*)(objectCategory=Person))"
'"(sAMAccountName=" & UserName & "))"
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 & ";" & fltr & ";" & attr & ";" & scope
Set rs = cmd.Execute
strArr = Split(attr, ",")
ThisWorkbook.Worksheets("Data").[A1].Resize(1, UBound(strArr)) = strArr
y = 2
Do Until rs.EOF
For i = 0 To rs.Fields.Count - 1
ThisWorkbook.Worksheets("Data").Cells(y, i + 1).Value = rs.Fields(i).Value
Next i
y = y + 1
rs.movenext
Loop
rs.Close
conn.Close
End Function
I am using a macro that pulls employee names from an active directory using a department number. I need to be able to display each employee found into a cell range, preferably Range("A1:A10"). My current macro is listing all the results into Range("B3"). Any help with this would be appreciated. I've broken down my code in two parts. 1st part gets called when employee clicks on a button from a userform, second part is a function that connects to active directory:
Sub is linked to a Command Button on a userform
Sub opsldap()
Dim ws As Worksheet
Set ws = Sheets("Sheet1")
struser = opslogin.TextBox1
struserdn = Get_LDAP_User_Properties("user", "department", struser, "displayName")
If Len(struserdn) <> 0 Then
ws.Range("B3").Value = struserdn
MsgBox "Welcome to Op's Vision " & struserdn
Else
MsgBox "Cant Find"
End If
End Sub
Function to get results from Active Directory
Function Get_LDAP_User_Properties(strObjectType, strSearchField, strObjectToGet, strCommaDelimProps)
On Error GoTo EarlyExit
If InStr(strObjectToGet, "\") > 0 Then
arrGroupBits = Split(strObjectToGet, "\")
strDC = arrGroupBits(0)
strDNSDomain = strDC & "/" & "DC=" & Replace(Mid(strDC, InStr(strDC, ".") + 1), ".", ",DC=")
strObjectToGet = arrGroupBits(1)
Else
' Otherwise we just connect to the default domain
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")
End If
strBase = "<LDAP://" & strDNSDomain & ">"
' Setup ADO objects.
Set adoCommand = CreateObject("ADODB.Command")
Set ADOConnection = CreateObject("ADODB.Connection")
ADOConnection.Provider = "ADsDSOObject"
ADOConnection.Open "Active Directory Provider"
adoCommand.ActiveConnection = ADOConnection
' Filter on user objects.
'strFilter = "(&(objectCategory=person)(objectClass=user))"
strFilter = "(&(objectClass=" & strObjectType & ")(" & strSearchField & "=" & strObjectToGet & "))"
' Comma delimited list of attribute values to retrieve.
strAttributes = strCommaDelimProps
arrProperties = Split(strCommaDelimProps, ",")
' Construct the LDAP syntax query.
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
adoCommand.CommandText = strQuery
' Define the maximum records to return
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False
' Run the query.
Set adoRecordset = adoCommand.Execute
' Enumerate the resulting recordset.
strReturnVal = ""
Do Until adoRecordset.EOF
' Retrieve values and display.
For intCount = LBound(arrProperties) To UBound(arrProperties)
If strReturnVal = "" Then
strReturnVal = adoRecordset.Fields(intCount).Value
Else
strReturnVal = strReturnVal & vbCrLf & adoRecordset.Fields(intCount).Value
End If
Next
' Move to the next record in the recordset.
adoRecordset.MoveNext
Loop
' Clean up.
adoRecordset.Close
ADOConnection.Close
Get_LDAP_User_Properties = strReturnVal
EarlyExit:
On Error GoTo 0
End Function
Here is the split array I am using:
Sub opsldap()
Dim textstring As String, Warray() As String, counter As Integer, strg As String
struser = opslogin.TextBox1
struserdn = Get_LDAP_User_Properties("user", "department", struser, "displayName")
If Len(struserdn) <> 0 Then
textstring = struserdn
Warray() = split(textstring, vbNewLine)
For counter = LBound(Warray) To UBound(Warray)
strg = Warray(counter)
Cells(counter + 3, 1).Value = Trim(strg)
Next counter
Else
MsgBox "I couldnt locate that cost center"
End If
End Sub
SOLVED. Solution at bottom!
Hopefully you brainiacs can help me out as I've apparently reached the limit of my programming capabilities.
I am looking for a way to write a VBA sub which duplicates another VBA Sub, but replace the name and another input. The case in details:
I am trying to build an Excel template for the organization, which will allow the users to inport/export data to/from Access databases (.accdb), as the end-users reluctance towards using real databases (as opposed to excel lists) apparently lies in their inability to extract/submit the data to/from Excel, where they are comfortable working with the data.
The challenge is, that users who don't know how to link to Access, for sure don't know anything about VBA code. Hence, I have created a worksheet from which the users selects a database using a file-path, table, password, set filters, define where to copy/insert datasets, fields to import etc. A Macro then handles the rest.
However, I want to create a macro which allows the user to create additional database links. As it is right now, this would require the user to open VBE and copy two macros and change one line of code... but that is a recipe for disaster. So how can I add a button to the sheet that copies the code I have written and rename the macro?
... I was considering if using a function, but cannot get my head around how that should Work.
Does it make sense? Any ideas/ experiences? Is there a completely different way around it that I haven't considered?
I'd really appreciate your inputs - even if this turns out to be impossible.
Edit:
Macro Man, you asked for the code - it's rather long due to all the user input fields, so I was trying to save you Guys for it since the code in and of itself is working fine...
Sub GetData1()
' Click on Tools, References and select
' the Microsoft ActiveX Data Objects 2.0 Library
Dim DBFullName As String
Dim Connect As String, Source As String
Dim Connection As ADODB.Connection
Dim Recordset As ADODB.Recordset
Dim Col As Integer
Dim DBInfoLocation As Range
Dim PW As String
Dim WSforData As String
Dim CellforData As String
Dim FieldList As Integer
'******************************
'Enter location for Database conectivity details below:
'******************************
Set DBInfoLocation = ActiveWorkbook.Sheets("DBLinks").Range("C15:I21")
FieldList = ActiveWorkbook.Sheets("DBLinks").Range("P1").Value
'******************************
' Define data location
WSforData = DBInfoLocation.Rows(4).Columns(1).Value
CellforData = DBInfoLocation.Rows(5).Columns(1).Value
'Set filters
Dim FilField1, FilField2, FilFieldA, FilFieldB, FilFieldC, FilFieldD, FilFieldE, FilOperator1, FilOperator2, FilOperatorA, FilOperatorB, FilOperatorC, FilOperatorD, FilOperatorE, FilAdMth1, FilAdMthA, FilAdMthB, FilAdMthC, FilAdMthD As String
Dim Filtxt1, Filtxt2, FiltxtA, FiltxtB, FiltxtC, FiltxtD, FiltxtE As String
Dim ExtFld1, ExtFld2, ExtFld3, ExtFld4, ExtFld5, ExtFld6, ExtFld7, ExtFld As String
Dim FilCnt, FilCntA As Integer
Dim FilVar1 As String
'Set DB field names
FilField1 = DBInfoLocation.Rows(1).Columns(5).Value
FilField2 = DBInfoLocation.Rows(2).Columns(5).Value
FilFieldA = DBInfoLocation.Rows(3).Columns(5).Value
FilFieldB = DBInfoLocation.Rows(4).Columns(5).Value
FilFieldC = DBInfoLocation.Rows(5).Columns(5).Value
FilFieldD = DBInfoLocation.Rows(6).Columns(5).Value
FilFieldE = DBInfoLocation.Rows(7).Columns(5).Value
'Set filter operators
FilOperator1 = DBInfoLocation.Rows(1).Columns(6).Value
FilOperator2 = DBInfoLocation.Rows(2).Columns(6).Value
FilOperatorA = DBInfoLocation.Rows(3).Columns(6).Value
FilOperatorB = DBInfoLocation.Rows(4).Columns(6).Value
FilOperatorC = DBInfoLocation.Rows(5).Columns(6).Value
FilOperatorD = DBInfoLocation.Rows(6).Columns(6).Value
FilOperatorE = DBInfoLocation.Rows(7).Columns(6).Value
'Run through criteria to find VarType(FilCrit1) (the Dimension data type) for the criteria field and set the appropriate data type for the filter
currentLoad = IIf(IsNumeric(DBInfoLocation.Rows(1).Columns(7).Value), CDbl(FilCrit1), IIf((DBInfoLocation.Rows(1).Columns(7).Value = "True" Or DBInfoLocation.Rows(1).Columns(7).Value = "False"), CBool(FilCrit1), IIf(IsDate(DBInfoLocation.Rows(1).Columns(7).Value), CDate(FilCrit1), CStr(FilCrit1))))
currentLoad = IIf(IsNumeric(DBInfoLocation.Rows(2).Columns(7).Value), CDbl(FilCrit2), IIf((DBInfoLocation.Rows(2).Columns(7).Value = "True" Or DBInfoLocation.Rows(2).Columns(7).Value = "False"), CBool(FilCrit2), IIf(IsDate(DBInfoLocation.Rows(2).Columns(7).Value), CDate(FilCrit2), CStr(FilCrit2))))
currentLoad = IIf(IsNumeric(DBInfoLocation.Rows(3).Columns(7).Value), CDbl(FilCrit3), IIf((DBInfoLocation.Rows(3).Columns(7).Value = "True" Or DBInfoLocation.Rows(3).Columns(7).Value = "False"), CBool(FilCrit3), IIf(IsDate(DBInfoLocation.Rows(3).Columns(7).Value), CDate(FilCrit3), CStr(FilCrit3))))
currentLoad = IIf(IsNumeric(DBInfoLocation.Rows(4).Columns(7).Value), CDbl(FilCrit4), IIf((DBInfoLocation.Rows(4).Columns(7).Value = "True" Or DBInfoLocation.Rows(4).Columns(7).Value = "False"), CBool(FilCrit4), IIf(IsDate(DBInfoLocation.Rows(4).Columns(7).Value), CDate(FilCrit4), CStr(FilCrit4))))
currentLoad = IIf(IsNumeric(DBInfoLocation.Rows(5).Columns(7).Value), CDbl(FilCrit5), IIf((DBInfoLocation.Rows(5).Columns(7).Value = "True" Or DBInfoLocation.Rows(5).Columns(7).Value = "False"), CBool(FilCrit5), IIf(IsDate(DBInfoLocation.Rows(5).Columns(7).Value), CDate(FilCrit5), CStr(FilCrit5))))
currentLoad = IIf(IsNumeric(DBInfoLocation.Rows(6).Columns(7).Value), CDbl(FilCrit6), IIf((DBInfoLocation.Rows(6).Columns(7).Value = "True" Or DBInfoLocation.Rows(6).Columns(7).Value = "False"), CBool(FilCrit6), IIf(IsDate(DBInfoLocation.Rows(6).Columns(7).Value), CDate(FilCrit6), CStr(FilCrit6))))
currentLoad = IIf(IsNumeric(DBInfoLocation.Rows(7).Columns(7).Value), CDbl(FilCrit7), IIf((DBInfoLocation.Rows(7).Columns(7).Value = "True" Or DBInfoLocation.Rows(7).Columns(7).Value = "False"), CBool(FilCrit7), IIf(IsDate(DBInfoLocation.Rows(7).Columns(7).Value), CDate(FilCrit7), CStr(FilCrit7))))
'Set Filter criteria
FilCrit1 = DBInfoLocation.Rows(1).Columns(7).Value
FilCrit2 = DBInfoLocation.Rows(2).Columns(7).Value
FilCrit3 = DBInfoLocation.Rows(3).Columns(7).Value
FilCrit4 = DBInfoLocation.Rows(4).Columns(7).Value
FilCrit5 = DBInfoLocation.Rows(5).Columns(7).Value
FilCrit6 = DBInfoLocation.Rows(6).Columns(7).Value
FilCrit7 = DBInfoLocation.Rows(7).Columns(7).Value
'Set additional filter-method
FilAdMth1 = DBInfoLocation.Rows(1).Columns(8).Value
FilAdMthA = DBInfoLocation.Rows(3).Columns(8).Value
FilAdMthB = DBInfoLocation.Rows(4).Columns(8).Value
FilAdMthC = DBInfoLocation.Rows(5).Columns(8).Value
FilAdMthD = DBInfoLocation.Rows(6).Columns(8).Value
'Set which fields to extract
ExtFld1 = DBInfoLocation.Rows(1).Columns(9).Value
ExtFld2 = DBInfoLocation.Rows(2).Columns(9).Value
ExtFld3 = DBInfoLocation.Rows(3).Columns(9).Value
ExtFld4 = DBInfoLocation.Rows(4).Columns(9).Value
ExtFld5 = DBInfoLocation.Rows(5).Columns(9).Value
ExtFld6 = DBInfoLocation.Rows(6).Columns(9).Value
ExtFld7 = DBInfoLocation.Rows(7).Columns(9).Value
'Filter on query
'Only criteria of value type string should have single quotation marks around them
FilCnt = 0
If FilField1 <> "" Then
If VarType(FilCrit1) = vbString Then
Filtxt1 = " WHERE [" & FilField1 & "] " & FilOperator1 & " '" & FilCrit1 & "'"
Else
Filtxt1 = " WHERE [" & FilField1 & "] " & FilOperator1 & " " & FilCrit1
End If
FilCnt = 1
End If
If FilField2 <> "" And FilCnt = 1 Then
If VarType(FilCrit2) = vbString Then
Filtxt2 = " " & FilAdMth1 & " [" & FilField2 & "] " & FilOperator2 & " '" & FilCrit2 & "'"
Else
Filtxt2 = " " & FilAdMth1 & " [" & FilField2 & "] " & FilOperator2 & " " & FilCrit2
End If
FilCnt = 2
End If
'Filter on Dataset
FilCntA = 0
If FilFieldA <> "" Then
If VarType(FilCrit3) = vbString Then
FiltxtA = FilFieldA & " " & FilOperatorA & " '" & FilCrit3 & "'"
Else
FiltxtA = FilFieldA & " " & FilOperatorA & " " & FilCrit3
End If
FilCntA = 1
End If
If FilFieldB <> "" And FilCntA = 1 Then
If VarType(FilCrit4) = vbString Then
FiltxtB = " " & FilAdMthA & " " & FilFieldB & " " & FilOperatorB & " '" & FilCrit4 & "'"
Else
FiltxtB = " " & FilAdMthA & " " & FilFieldB & " " & FilOperatorB & " " & FilCrit4
End If
FilCntA = 2
End If
If FilFieldC <> "" And FilCntA = 2 Then
If VarType(FilCrit5) = vbString Then
FiltxtC = " " & FilAdMthB & " " & FilFieldC & " " & FilOperatorC & " '" & FilCrit5 & "'"
Else
FiltxtC = " " & FilAdMthB & " " & FilFieldC & " " & FilOperatorC & " " & FilCrit5
End If
FilCntA = 3
End If
If FilFieldD <> "" And FilCntA = 3 Then
If VarType(FilCrit6) = vbString Then
FiltxtD = " " & FilAdMthC & " " & FilFieldD & " " & FilOperatorD & " '" & FilCrit6 & "'"
Else
FiltxtD = " " & FilAdMthC & " " & FilFieldD & " " & FilOperatorD & " " & FilCrit6
End If
FilCntA = 4
End If
If FilFieldE <> "" And FilCntA = 4 Then
If VarType(FilCrit7) = vbString Then
FiltxtE = " " & FilAdMthD & " " & FilFieldE & " " & FilOperatorE & " '" & FilCrit7 & "'"
Else
FiltxtE = " " & FilAdMthD & " " & FilFieldE & " " & FilOperatorE & " " & FilCrit7
End If
FilCntA = 5
End If
' Select Fields to Extract
ExtFld = "*"
If ExtFld1 <> "" Then
ExtFld = "[" & ExtFld1 & "]"
End If
If ExtFld2 <> "" Then
ExtFld = "[" & ExtFld1 & "],[" & ExtFld2 & "]"
End If
If ExtFld3 <> "" Then
ExtFld = "[" & ExtFld1 & "],[" & ExtFld2 & "],[" & ExtFld3 & "]"
End If
If ExtFld4 <> "" Then
ExtFld = "[" & ExtFld1 & "],[" & ExtFld2 & "],[" & ExtFld3 & "],[" & ExtFld4 & "]"
End If
If ExtFld5 <> "" Then
ExtFld = "[" & ExtFld1 & "],[" & ExtFld2 & "],[" & ExtFld3 & "],[" & ExtFld4 & "],[" & ExtFld5 & "]"
End If
If ExtFld6 <> "" Then
ExtFld = "[" & ExtFld1 & "],[" & ExtFld2 & "],[" & ExtFld3 & "],[" & ExtFld4 & "],[" & ExtFld5 & "],[" & ExtFld6 & "]"
End If
If ExtFld7 <> "" Then
ExtFld = "[" & ExtFld1 & "],[" & ExtFld2 & "],[" & ExtFld3 & "],[" & ExtFld4 & "],[" & ExtFld5 & "],[" & ExtFld6 & "],[" & ExtFld7 & "]"
End If
' Database path info
PW = DBInfoLocation.Rows(3).Columns(1).Value
' Your path will be different
DBFullName = DBInfoLocation.Rows(1).Columns(1).Value
DBTable = DBInfoLocation.Rows(2).Columns(1).Value
' Open the connection
Set Connection = New ADODB.Connection
Connect = "Provider=Microsoft.ACE.OLEDB.12.0;"
Connect = Connect & "Data Source=" & DBFullName & ";Jet OLEDB:Database Password=" & PW & ";"
Connection.Open ConnectionString:=Connect
' Create RecordSet & Define data to extract
Set Recordset = New ADODB.Recordset
With Recordset
'Get All Field Names by opening the DB, extracting a recordset, entering the field names and closing the dataset
Source = DBTable
.Open Source:=Source, ActiveConnection:=Connection
For ColH = 0 To Recordset.Fields.Count - 1
ActiveWorkbook.Worksheets("DBLinks").Range("A1").Offset(ColH + 3, FieldList - 1).Cells.Clear
ActiveWorkbook.Worksheets("DBLinks").Range("A1").Offset(ColH + 3, FieldList - 1).Value = Recordset.Fields(ColH).Name
ActiveWorkbook.Worksheets("RangeNames").Range("A1").Offset(ColH + 2, (DBInfoLocation.Rows(1).Columns(2).Value) - 1).Cells.Clear
ActiveWorkbook.Worksheets("RangeNames").Range("A1").Offset(ColH + 2, (DBInfoLocation.Rows(1).Columns(2).Value) - 1).Value = Recordset.Fields(ColH).Name
Next
Set Recordset = Nothing
End With
' Get the recordset, but only extract the field names of those defined in the spreadsheet.
' If no fields have been selected, all fields will be extracted.
Set Connection = New ADODB.Connection
Connect = "Provider=Microsoft.ACE.OLEDB.12.0;"
Connect = Connect & "Data Source=" & DBFullName & ";Jet OLEDB:Database Password=" & PW & ";"
Connection.Open ConnectionString:=Connect
Set Recordset = New ADODB.Recordset
With Recordset
If FilCnt = 0 Then 'No filter
Source = "SELECT " & ExtFld & " FROM " & DBTable
End If
' Filter Data if selected
If FilCnt = 1 Then
Source = "SELECT " & ExtFld & " FROM " & DBTable & Filtxt1
End If
If FilCnt = 2 Then
Source = "SELECT " & ExtFld & " FROM " & DBTable & Filtxt1 & Filtxt2
End If
.Open Source:=Source, ActiveConnection:=Connection
If FilCntA = 1 Then
Recordset.Filter = FiltxtA
End If
If FilCntA = 2 Then
Recordset.Filter = FiltxtA & FiltxtB
End If
If FilCntA = 3 Then
Recordset.Filter = FiltxtA & FiltxtB & FiltxtC
End If
If FilCntA = 4 Then
Recordset.Filter = FiltxtA & FiltxtB & FiltxtC & FiltxtD
End If
If FilCntA = 5 Then
Recordset.Filter = FiltxtA & FiltxtB & FiltxtC & FiltxtD & FiltxtE
End If
'Debug.Print Recordset.Filter
' Clear data
For Col = 0 To Recordset.Fields.Count - 1
If WSforData <> "" Then
ActiveWorkbook.Worksheets(WSforData).Range(CellforData).Offset(0, Col).EntireColumn.Clear
End If
'ActiveWorkbook.Worksheets("DBLinks").Range("A1").Offset(Col + 3, FieldList - 1).Cells.Clear
Next
' Write field names
For Col = 0 To Recordset.Fields.Count - 1
If WSforData <> "" Then
ActiveWorkbook.Worksheets(WSforData).Range(CellforData).Offset(0, Col).Value = Recordset.Fields(Col).Name
End If
Next
' Write recordset
If WSforData <> "" Then
ActiveWorkbook.Worksheets(WSforData).Range(CellforData).Offset(1, 0).CopyFromRecordset Recordset
ActiveWorkbook.Worksheets(WSforData).Columns.AutoFit
End If
End With
' Clear recordset and close connection
Set Recordset = Nothing
Connection.Close
Set Connection = Nothing
End Sub
This piece of the "DBLinks" worksheet is probably also needed for full understanding of the code:
DBLinks user input area for database connectivity
SOLUTION:
I followed the advice to look into VBProject.VBComponents which copied the macro. I created a simple form which asked for the name to use for the macro and the rest of the inputs comes from the relative reference. I will spare you for a full copy of my long and less than graceful code, but the essential of the code are:
In case someone else could benefit from my experience: In the Click-action of the command button on the form:
Private Sub cmdCreateDB_Click()
'Go to Tools, References and add: Microsoft Visual Basic for Applications Extensibility 5.3
Dim VBProj As VBIDE.VBProject
Dim VBComp As VBIDE.VBComponent
Dim CodeMod As VBIDE.CodeModule
Dim LineNum As Long
Const DQUOTE = """" ' one " character
Set VBProj = ActiveWorkbook.VBProject
Set VBComp = VBProj.VBComponents("Module1")
Set CodeMod = VBComp.CodeModule
Dim txtDBLinkName As String
txtDBLinkName = Me.txtDBName
With CodeMod
LineNum = .CountOfLines + 1
.InsertLines LineNum, " Sub " & txtDBLinkName & "()"
LineNum = LineNum + 1
.InsertLines LineNum, " ' Click on Tools, References and select"
LineNum = LineNum + 1
.InsertLines LineNum, " ' the Microsoft ActiveX Data Objects 2.0 Library"
' And then it goes on forever through all the lines of the original code...
' just remember to replace all double quotations with(Without Square brackets):
' [" & DQUOTE & "]
'And it ends up with:
LineNum = LineNum + 1
.InsertLines LineNum, " Set Recordset = Nothing"
LineNum = LineNum + 1
.InsertLines LineNum, " Connection.Close"
LineNum = LineNum + 1
.InsertLines LineNum, " Set Connection = Nothing"
LineNum = LineNum + 1
.InsertLines LineNum, " End Sub"
End With
Unload Me
End Sub
Thank you everyone for your help. - Especially you #findwindow for coming up with the path to a solution.
For the sake of completion, here's how this could be dealt with without metaprogramming.
Problems that boil down to "do the same thing - but..." can often be solved by making the program as generic as possible. All data specific to a single use-case should be passed down from above in a clear manner, allowing the program to be reused.
Let's look at an example of how this could be implemented in order to generate query strings from one or many ranges of varying sizes.
The first step is to group all data that belongs to the concept of a Filter. Since VBA doesn't have object literals, we can use an Array, a Collection or a Type to represent a Filter instead.
Generating the query strings requires distinction between QueryFilters and RecordFilters. Looking at the code, the two variants are similar enough to be handled by a simple Boolean within a single Type.
Option Explicit
Private Type Filter
Field As String
Operator As String
Criteria As Variant
AdditionalMethod As String
ExtractedFields As String
IsQueryFilter As Boolean
FilterString As String
End Type
Now we can use a single variable instead of keeping track of multiple variables to represent a single concept.
One way a Filter can be generated is by using a Range.
' Generates a Filter from a given Range of input data.
Private Function GenerateFilter(ByRef source As Range) As Filter
With GenerateFilter
.Field = CStr(source)
.Operator = CStr(source.Offset(0, 1))
.Criteria = source.Offset(0, 2)
.AdditionalMethod = CStr(source.Offset(0, 3))
.ExtractedFields = CStr(source.Offset(0, 4))
.IsQueryFilter = CBool(source.Offset(0, 5))
.FilterString = GenerateFilterString(GenerateFilter)
End With
End Function
Just as a single concept can be declared as a Type, a group of things can be declared as an Array (or a Collection, Dictionary, ...). This is useful, as it lets us decouple the logic from a specific Range.
' Generates a Filter for each row of a given Range of input data.
Private Function GenerateFilters(ByRef source As Range) As Filter()
Dim filters() As Filter
Dim filterRow As Range
Dim i As Long
ReDim filters(0 To source.Rows.Count)
i = 0
For Each filterRow In source.Rows
filters(i) = GenerateFilter(filterRow)
i = i + 1
Next
GenerateFilters = filters()
End Function
We now have a function that can return an Array of Filters from a given Range - and, as long as the columns are laid down in the right order, the code will work just fine with any Range.
With all of the data in a convenient package, it's easy enough to assemble the FilterString.
' Generates a FilterString for a given Filter.
Private Function GenerateFilterString(ByRef aFilter As Filter) As String
Dim temp As String
temp = " "
With aFilter
If .AdditionalMethod <> "" Then temp = temp & .AdditionalMethod & " "
If .IsQueryFilter Then
temp = temp & "[" & .Field & "]"
Else
temp = temp & .Field
End If
temp = temp & " " & .Operator & " "
If VarType(.Criteria) = vbString Then
temp = temp & "'" & .Criteria & "'"
Else
temp = temp & .Criteria
End If
End With
GenerateFilterString = temp
End Function
The data can then be merged to strings that can be used in queries regardless of how many Filters of either type are present in the specified Range.
' Merges the FilterStrings of Filters that have IsQueryString set as True.
Private Function MergeQueryFilterStrings(ByRef filters() As Filter) As String
Dim temp As String
Dim i As Long
temp = " WHERE"
For i = 0 To UBound(filters)
If filters(i).IsQueryFilter Then temp = temp & filters(i).FilterString
Next
MergeQueryFilterStrings = temp
End Function
' Merges the FilterStrings of Filters that have IsQueryString set as False.
Private Function MergeRecordFilterStrings(ByRef filters() As Filter) As String
Dim temp As String
Dim i As Long
For i = 0 To UBound(filters)
If Not filters(i).IsQueryFilter Then _
temp = temp & filters(i).FilterString
Next
MergeRecordFilterStrings = temp
End Function
' Merges the ExtractedFields of all Filters.
Private Function MergeExtractedFields(ByRef filters() As Filter) As String
Dim temp As String
Dim i As Long
temp = ""
For i = 0 To UBound(filters)
If filters(i).ExtractedFields <> "" Then _
temp = temp & "[" & filters(i).ExtractedFields & "],"
Next
If temp = "" Then
temp = "*"
Else
temp = Left(temp, Len(temp) - 1) ' Remove dangling comma.
End If
MergeExtractedFields = temp
End Function
With all of that done, we can finally plug a single Range in and get the generated strings out. It would be trivial to change filterRange or generate Filters from multiple Ranges.
Public Sub TestStringGeneration()
Dim filters() As Filter
Dim filterRange As Range
Set filterRange = Range("A1:A10")
filters = GenerateFilters(filterRange)
Debug.Print MergeQueryFilterStrings(filters)
Debug.Print MergeRecordFilterStrings(filters)
Debug.Print MergeExtractedFields(filters)
End Sub
TL;DR
Split code to reusable Functions & Subs
Favor sending data as arguments
Avoid hard-coding
Group data that represent a single concept
Use Arrays or other data structures over multiple variables
Im sorry about the large amount of code but I've been looking over a number of days now to try and resolve this problem. Basically this code runs in outlook when I start it up. It exports different types of emails from different inbox's where different subject headers exist.
It collects parts of the subject heading and parts of the email body and exports this as text into my excel spreadsheet.
The problem I have is that this code actually works fine, and it use to open an excel spreadsheet in the background and export the information into a new row in the relevant columns. Once it has done this it would automatically save the spreadsheet and close.
Now however for some reason, it will do all of that but will not close the spreadsheet and Excel shows up as a running service in windows task manager. This should not be the case and the spreadsheet should save changes and close automatically.
'On the next line edit the path to the spreadsheet you want to export to
Const WORKBOOK_PATH = "X:\New_Supplier_Set_Ups_&_Audits\Supplier SetUps & Amendments.xls"
'On the next line edit the name of the sheet you want to export to
Const SHEET_NAME = "Validations"
Const SHEET_NAME2 = "BankSetup"
Const SHEET_NAME3 = "CreditChecks"
Const SHEET_NAME4 = "Statistics"
Const MACRO_NAME = "Export Messages to Excel (Rev 7)"
Const xlContinuous As Integer = 1
Const vbBlack As Integer = 0
Const xlThin As Integer = 2
Dim olkMsg As Object, _
olkMsg2 As Object, _
excApp As Object, _
excWkb As Object, _
excWks As Object, _
excWks2 As Object, _
excWks3 As Object, _
excWks4 As Object, _
intRow As Integer, _
intRow2 As Integer, _
intRow3 As Integer, _
intRow4 As Integer, _
intExp As Integer, _
intVersion As Integer
intVersion = GetOutlookVersion()
Set excApp = CreateObject("Excel.Application")
Set excWkb = excApp.Workbooks.Open(WORKBOOK_PATH)
Set excWks = excWkb.Worksheets(SHEET_NAME)
Set excWks2 = excWkb.Worksheets(SHEET_NAME2)
Set excWks3 = excWkb.Worksheets(SHEET_NAME3)
Set excWks4 = excWkb.Worksheets(SHEET_NAME4)
intRow = excWks.UsedRange.Rows.Count + 1
intRow2 = excWks2.UsedRange.Rows.Count + 1
intRow3 = excWks3.UsedRange.Rows.Count + 1
intRow4 = excWks4.UsedRange.Rows.Count + 1
'Write messages to spreadsheet
Dim ns As Outlook.NameSpace
Dim Items As Outlook.Items
Dim Items2 As Outlook.Items
Dim objAttachments As Outlook.Attachments
Dim objMsg As Outlook.MailItem 'Object
Dim i As Long
Dim lngCount As Long
Dim strFile As String
Dim strFolderpath As String
Dim strDeletedFiles As String
Dim withParts As String
Dim withoutParts As String
' Get the MAPI Namespace
Set ns = Application.GetNamespace("MAPI")
' Get the Items for the Inbox in the specified account
Set Items = ns.Folders("New Suppliers").Folders("Inbox").Items
Set Items2 = ns.Folders("Credit Checks").Folders("Inbox").Items
' Start looping through the items
For Each olkMsg In Items
'Only export messages, not receipts or appointment requests, etc.
If olkMsg.UnRead = True Then
If olkMsg.class = olMail Then
If olkMsg.Subject Like "Accept: (Update) New Supplier Request*" Or olkMsg.Subject Like "Accept: (Approval Required) - New Supplier Request*" Or olkMsg.Subject Like "Reject: (Approval Required) - New Supplier Request*" Or olkMsg.Subject Like "Accept: (IMPORTANT REMINDER!) - New Supplier Request*" Then
'Add a row for each field in the message you want to export
excWks.Cells(intRow, 1) = olkMsg.ReceivedTime
Dim LResult As String
LResult = Replace(GetSMTPAddress(olkMsg, intVersion), ".", " ")
LResult = Left(LResult, InStrRev(LResult, "#") - 1)
excWks.Cells(intRow, 2) = LResult
excWks.Cells(intRow, 3) = olkMsg.VotingResponse
Dim s As String
s = olkMsg.Subject
Dim indexOfName As Integer
indexOfName = InStr(1, s, "Reference: ")
Dim finalString As String
finalString = Right(s, Len(s) - indexOfName - 10)
excWks.Cells(intRow, 4) = finalString
intRow = intRow + 1
olkMsg.UnRead = False
End If
End If
If olkMsg.class = olMail Then
If olkMsg.Subject Like "Complete: Bank Details Set-Up for New Supplier*" Or olkMsg.Subject Like "Incomplete: Bank Details Set-Up for New Supplier*" Then
'Add a row for each field in the message you want to export
excWks2.Cells(intRow2, 1) = olkMsg.ReceivedTime
Dim LResult2 As String
LResult2 = Replace(GetSMTPAddress(olkMsg, intVersion), ".", " ")
LResult2 = Left(LResult2, InStrRev(LResult2, "#") - 1)
excWks2.Cells(intRow2, 2) = LResult2
excWks2.Cells(intRow2, 3) = olkMsg.VotingResponse
Dim s2 As String
s2 = olkMsg.Subject
Dim indexOfName2 As Integer
indexOfName2 = InStr(1, s2, "Reference: ")
Dim finalString2 As String
finalString2 = Right(s2, Len(s2) - indexOfName2 - 10)
excWks2.Cells(intRow2, 4) = finalString2
intRow2 = intRow2 + 1
olkMsg.UnRead = False
End If
End If
If olkMsg.class = olMail Then
If olkMsg.Subject Like "New Supplier Request - Reference:*" Then
'Add a row for each field in the message you want to export
Dim FSO As Object
Dim FolderPath As String
Set FSO = CreateObject("scripting.filesystemobject")
Dim b4 As String
Dim strNewFolderName As String
If TypeName(olkMsg) = "MailItem" Then
b4 = olkMsg.Body
Dim indexOfNameb As Integer
indexOfNameb = InStr(UCase(b4), UCase("Company name: "))
Dim indexOfNamec As Integer
indexOfNamec = InStr(UCase(b4), UCase("Company number: "))
Dim finalStringb As String
finalStringb = Mid(b4, indexOfNameb, indexOfNamec - indexOfNameb)
LResult336 = Replace(finalStringb, "Company Name: ", "")
Dim LResult21 As String
Dim LResult211 As String
Dim LResult2113 As String
LResult21 = Trim(LResult336)
LResult211 = Replace(LResult21, Chr(10), "")
LResult2113 = Replace(LResult211, Chr(13), "")
excWks4.Cells(intRow4, 2) = Trim(LResult2113)
FolderPath = "\\uksh000-file06\purchasing\New_Supplier_Set_Ups_&_Audits\ATTACHMENTS\" & Trim(LResult2113)
If FSO.FolderExists(FolderPath) = False Then
Dim strDir As String
strDir = "\\uksh000-file06\purchasing\New_Supplier_Set_Ups_&_Audits\ATTACHMENTS\" & Trim(LResult2113)
If Dir(strDir, vbDirectory) = "" Then
MkDir strDir
FileCopy "X:\New_Supplier_Set_Ups_&_Audits\assets\audit.xls", "X:\New_Supplier_Set_Ups_&_Audits\ATTACHMENTS\" & Trim(LResult2113) & "\audit.xls"
Else
MsgBox "Directory exists."
End If
Else
End If
End If
Dim b5 As String
If TypeName(olkMsg) = "MailItem" Then
b5 = olkMsg.Body
Dim indexOfNameb2 As Integer
indexOfNameb2 = InStr(UCase(b5), UCase("Company Number: "))
Dim indexOfNamec2 As Integer
indexOfNamec2 = InStr(UCase(b5), UCase("VAT Number: "))
Dim finalStringb2 As String
finalStringb2 = Mid(b5, indexOfNameb2, indexOfNamec2 - indexOfNameb2)
LResult3362 = Replace(finalStringb2, "Company Number: ", "")
excWks4.Cells(intRow4, 3) = LResult3362
End If
Dim b6 As String
If TypeName(olkMsg) = "MailItem" Then
b6 = olkMsg.Body
Dim indexOfNameb3 As Integer
indexOfNameb3 = InStr(UCase(b6), UCase("VAT Number: "))
Dim indexOfNamec3 As Integer
indexOfNamec3 = InStr(UCase(b6), UCase("Contact Name: "))
Dim finalStringb3 As String
finalStringb3 = Mid(b6, indexOfNameb3, indexOfNamec3 - indexOfNameb3)
LResult3363 = Replace(finalStringb3, "VAT Number: ", "")
excWks4.Cells(intRow4, 4) = LResult3363
End If
Dim l As String
excWks4.Cells(intRow4, 5) = Trim(excWks4.Cells(intRow4, 5))
l = excWks4.Cells(intRow4, 5).Address
excWks4.Cells(intRow4, 6).FormulaArray = "=IF(ISERROR(INDEX('Up'!$A$1:$G$10004,SMALL(IF(LEFT('Up'!$B$1:$B$10004,5)=LEFT(" & l & ",5),ROW($B$1:$B$10004)),ROW(1:1)),6)),""ZZZ"",INDEX('Up'!$A$1:$G$10004,SMALL(IF(LEFT('Up'!$B$1:$B$10004,5)=LEFT(" & l & ",5),ROW($B$1:$B$10004)),ROW(1:1)),6))"
Dim b7 As String
If TypeName(olkMsg) = "MailItem" Then
b7 = olkMsg.Body
Dim indexOfNameb4 As Integer
indexOfNameb4 = InStr(UCase(b7), UCase("Description of the provisional Supplier:"))
Dim indexOfNamec4 As Integer
indexOfNamec4 = InStr(UCase(b7), UCase("Current Status: "))
Dim finalStringb4 As String
Dim LResult3364 As String
Dim LResult33644 As String
Dim LResult336445 As String
finalStringb4 = Mid(b7, indexOfNameb4, indexOfNamec4 - indexOfNameb4)
LResult3364 = Replace(finalStringb4, "Description of the provisional Supplier:", "")
LResult33644 = Replace(LResult3364, Chr(10), "")
LResult336445 = Replace(LResult33644, Chr(13), "")
Dim TrimString As String
TrimString = Trim(LResult336445)
excWks4.Cells(intRow4, 5) = Trim(TrimString)
End If
Dim b77 As String
If TypeName(olkMsg) = "MailItem" Then
b77 = olkMsg.Body
Dim indexOfNameb47 As Integer
indexOfNameb47 = InStr(UCase(b77), UCase("Contact Number: "))
Dim indexOfNamec47 As Integer
indexOfNamec47 = InStr(UCase(b77), UCase("Contact Email: "))
Dim finalStringb47 As String
Dim LResult33647 As String
Dim LResult336447 As String
Dim LResult3364457 As String
finalStringb47 = Mid(b77, indexOfNameb47, indexOfNamec47 - indexOfNameb47)
LResult33647 = Replace(finalStringb47, "Contact Number: ", "")
LResult336447 = Replace(LResult33647, Chr(10), "")
LResult3364457 = Replace(LResult336447, Chr(13), "")
Dim TrimString7 As String
TrimString7 = Trim(LResult3364457)
excWks4.Cells(intRow4, 11) = Trim(TrimString7)
End If
Dim b777 As String
If TypeName(olkMsg) = "MailItem" Then
b777 = olkMsg.Body
Dim indexOfNameb477 As Integer
indexOfNameb477 = InStr(UCase(b777), UCase("Contact Email: "))
Dim indexOfNamec477 As Integer
indexOfNamec477 = InStr(UCase(b777), UCase("Case Reference: "))
Dim finalStringb477 As String
Dim LResult336477 As String
Dim LResult3364477 As String
Dim LResult33644577 As String
finalStringb477 = Mid(b777, indexOfNameb477, indexOfNamec477 - indexOfNameb477)
LResult336477 = Replace(finalStringb477, "Contact Email: ", "")
LResult3364477 = Replace(LResult336477, Chr(10), "")
LResult33644577 = Replace(LResult3364477, Chr(13), "")
Dim TrimString77 As String
TrimString77 = Trim(LResult33644577)
excWks4.Cells(intRow4, 12) = Trim(TrimString77)
End If
Dim b7777 As String
If TypeName(olkMsg) = "MailItem" Then
b7777 = olkMsg.Body
Dim indexOfNameb4777 As Integer
indexOfNameb4777 = InStr(UCase(b7777), UCase("Requested Payment Term: "))
Dim indexOfNamec4777 As Integer
indexOfNamec4777 = InStr(UCase(b7777), UCase("Description of the provisional Supplier: "))
Dim finalStringb4777 As String
Dim LResult3364777 As String
Dim LResult33644777 As String
Dim LResult336445777 As String
finalStringb4777 = Mid(b7777, indexOfNameb4777, indexOfNamec4777 - indexOfNameb4777)
LResult3364777 = Replace(finalStringb4777, "Requested Payment Term: ", "")
LResult33644777 = Replace(LResult3364777, Chr(10), "")
LResult336445777 = Replace(LResult33644777, Chr(13), "")
Dim TrimString777 As String
TrimString777 = Trim(LResult336445777)
excWks4.Cells(intRow4, 29) = TrimString777
End If
Dim s4 As String
s4 = olkMsg.Subject
Dim indexOfName4 As Integer
indexOfName4 = InStr(1, s4, "Reference: ")
Dim finalString4 As String
finalString4 = Right(s4, Len(s4) - indexOfName2 - 34)
excWks4.Cells(intRow4, 7) = finalString4
excWks4.Cells(intRow4, 9) = "Pending"
excWks4.Cells(intRow4, 10).Formula = "=IF(" & excWks4.Cells(intRow4, 25).Address & "=""Declined"",""Manager has Declined"",IF(" & excWks4.Cells(intRow4, 25).Address & "<>""Yes"",IFERROR(CONCATENATE(""Manager has "" & INDEX(Validations!$C$1:$C$9958,MATCH(" & excWks4.Cells(intRow4, 7).Address & ",Validations!$D$1:$D$9958,0))),IF((TODAY()-" & excWks4.Cells(intRow4, 13).Address & ")>=5,""Approval Is Overdue"",""Approval Is Pending"")),IFERROR(CONCATENATE(""Manager has "" & INDEX(Validations!$C$1:$C$9958,MATCH(" & excWks4.Cells(intRow4, 7).Address & ",Validations!$D$1:$D$9958))),""Approval Overidden"")))"
excWks4.Cells(intRow4, 15) = "Pending"
excWks4.Cells(intRow4, 13) = olkMsg.ReceivedTime
Dim LResult33 As String
LResult33 = Replace(GetSMTPAddress(olkMsg, intVersion), ".", " ")
LResult33 = Left(LResult33, InStrRev(LResult33, "#") - 1)
excWks4.Cells(intRow4, 17) = LResult33
excWks4.Cells(intRow4, 18) = "=IFERROR(INDEX('Depot Data'!$F$1:$F$10004,MATCH(" & excWks4.Cells(intRow4, 17).Address & ",'Depot Data'!$E$1:$E$10004,0)),"""")"
excWks4.Cells(intRow4, 19) = "=IFERROR(INDEX('Depot Data'!$H$1:$H$10004,MATCH(" & excWks4.Cells(intRow4, 17).Address & ",'Depot Data'!$E$1:$E$10004,0)),"""")"
excWks4.Cells(intRow4, 20) = "Yes"
excWks4.Cells(intRow4, 23) = "Attach"
excWks4.Cells(intRow4, 24) = "Audit"
excWks4.Cells(intRow4, 25).Formula = "No"
excWks4.Cells(intRow4, 27) = "=Username()"
excWks4.Cells(intRow4, 28) = "Pending"
excWks4.Cells(intRow4, 31) = "V0000847"
excWks4.Cells(intRow4, 32) = "Action"
excWks4.Cells(intRow4, 33) = 1
excWks4.Cells(intRow4, 33).Interior.ColorIndex = 35
Dim LResult21234 As String
LResult21234 = GetSMTPAddress(olkMsg, intVersion)
excWks4.Cells(intRow4, 34) = "=HYPERLINK(""\\UKSH000-FILE06\Purchasing\New_Supplier_Set_Ups_&_Audits\ATTACHMENTS\" & Trim(LResult2113) & "\log.txt"",""Log"")"
Set fs = CreateObject("Scripting.FileSystemObject")
Set a = fs.CreateTextFile("\\UKSH000-FILE06\Purchasing\New_Supplier_Set_Ups_&_Audits\ATTACHMENTS\" & Trim(LResult2113) & "\log.txt", True)
a.WriteLine ("Log for Supplier: " & Trim(LResult2113) & " (Created: " & Date & ")")
a.WriteLine (Date & " - " & Time & " - Request received in NewSuppliers#Hewden.co.uk by " & LResult21234 & ", and added to New Supplier Database")
a.Close
Dim Rng As Object
Set Rng = excWks4.Range("B" & intRow4 & ":AH" & intRow4 & "")
With Rng.Borders
.LineStyle = xlContinuous
.Color = vbBlack
.Weight = xlThin
End With
excWks4.Range("B" & intRow4 & ":AH" & intRow4 & "").WrapText = False
intRow4 = intRow4 + 1
olkMsg.UnRead = False
If IsNumeric(LResult3362) Then
TempFilePath = "\\UKSH000-File06\Purchasing\New_Supplier_Set_Ups_&_Audits\assets\"
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = "<p style='color:#000;font-family:calibri;font-size:16'>" & "Dear New Accounts, " & vbNewLine & vbNewLine & _
"<br><B>F.A.O: Beth Crowe </b>" & vbNewLine & vbNewLine & _
"<br><br>" & "This is an automated email sent to you from New Suppliers. This is a credit refrence request." & vbNewLine & vbNewLine & _
"<br>" & "Please would you be able to perform a credit check on the following new supplier:" & vbNewLine & vbNewLine & _
"<br><br><br>" & "Company Name: " & "<b>" & Trim(LResult2113) & "</b>" & vbNewLine & vbNewLine & _
"<br>" & "Company Number: " & "<b>" & Trim(LResult3362) & "</b>" & vbNewLine & vbNewLine & _
"<br>" & "Case Reference Number (Purchasing Use Only): " & "<b>" & finalString4 & "</b>" & vbNewLine & vbNewLine & _
"<br><br><br>" & "In the event that you have any enquiries, please keep a note of the case reference number. For any questions please contact NewSuppliers#Hewden.co.uk." & vbNewLine & vbNewLine & _
"<br><br>" & "Kind Regards," & "</font></p>" & vbNewLine & _
"<p style='color:#000;font-family:calibri;font-size:18'><b>Hewden Supply Chain Department</b></font></p>" & vbNewLine & _
"<br><br><img src='cid:cover.jpg'" & "width='800' height='64'><br>" & vbNewLine & _
"<img src='cid:subs.jpg'" & "width='274' height='51'>"
With OutMail
.SentOnBehalfOfName = "newsuppliers#hewden.co.uk"
.To = "mark.o'brien#hewden.co.uk"
.CC = ""
.BCC = ""
.Subject = "(Credit Reference) New Supplier Credit Check - Reference: " & finalString4
.Attachments.Add TempFilePath & "cover.jpg", olByValue, 0
.Attachments.Add TempFilePath & "subs.jpg", olByValue, 0
.HtmlBody = strbody
'You can add a file like this
'.Attachments.Add ("C:\test.txt")
.Send 'or use .Display
End With
Else
Dim b9 As String
If TypeName(olkMsg) = "MailItem" Then
b9 = olkMsg.Body
Dim indexOfName9 As Integer
indexOfName9 = InStr(UCase(b9), UCase("Full Name of Tradesman: "))
Dim indexOfNam9 As Integer
indexOfNam9 = InStr(UCase(b9), UCase("D.O.B of Tradesman: "))
Dim finalString9 As String
finalString9 = Mid(b9, indexOfName9, indexOfNam9 - indexOfName9)
LResult3369 = Replace(finalString9, "Full Name of Tradesman: ", "")
End If
Dim b10 As String
If TypeName(olkMsg) = "MailItem" Then
b10 = olkMsg.Body
Dim indexOfName99 As Integer
indexOfName99 = InStr(UCase(b10), UCase("D.O.B of Tradesman: "))
Dim indexOfNam99 As Integer
indexOfNam99 = InStr(UCase(b10), UCase("Address of Tradesman: "))
Dim finalString99 As String
finalString99 = Mid(b10, indexOfName99, indexOfNam99 - indexOfName99)
LResult33699 = Replace(finalString99, "D.O.B of Tradesman: ", "")
End If
Dim b101 As String
If TypeName(olkMsg) = "MailItem" Then
b101 = olkMsg.Body
Dim indexOfName991 As Integer
indexOfName991 = InStr(UCase(b101), UCase("Address of Tradesman: "))
Dim indexOfNam991 As Integer
indexOfNam991 = InStr(UCase(b101), UCase("VAT Number: "))
Dim finalString991 As String
finalString991 = Mid(b101, indexOfName991, indexOfNam991 - indexOfName991)
LResult336991 = Replace(finalString991, "Address of Tradesman: ", "")
End If
TempFilePath = "\\UKSH000-File06\Purchasing\New_Supplier_Set_Ups_&_Audits\assets\"
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = "<p style='color:#000;font-family:calibri;font-size:16'>" & "Dear New Accounts, " & vbNewLine & vbNewLine & _
"<br><B>F.A.O: Beth Crowe </b>" & vbNewLine & vbNewLine & _
"<br><br>" & "This is an automated email sent to you from New Suppliers. This is a credit refrence request." & vbNewLine & vbNewLine & _
"<br>" & "Please would you be able to perform a credit check on the following new supplier:" & vbNewLine & vbNewLine & _
"<br><br><br>" & "Trading Name: " & "<b>" & Trim(LResult2113) & "</b>" & vbNewLine & vbNewLine & _
"<br>" & "Full Name of Tradesman: " & "<b>" & LResult3369 & "</b>" & vbNewLine & vbNewLine & _
"<br>" & "Tradesman Date of Birth: " & "<b>" & LResult33699 & "</b>" & vbNewLine & vbNewLine & _
"<br>" & "Tradesman Address: " & "<b>" & LResult336991 & "</b>" & vbNewLine & vbNewLine & _
"<br><br>" & "Case Reference Number (Purchasing Use Only): " & "<b>" & finalString4 & "</b>" & vbNewLine & vbNewLine & _
"<br><br><br>" & "In the event that you have any enquiries, please keep a note of the case reference number. For any questions please contact NewSuppliers#Hewden.co.uk." & vbNewLine & vbNewLine & _
"<br><br>" & "Kind Regards," & "</font></p>" & vbNewLine & _
"<p style='color:#000;font-family:calibri;font-size:18'><b>Hewden Supply Chain Department</b></font></p>" & vbNewLine & _
"<br><br><img src='cid:cover.jpg'" & "width='800' height='64'><br>" & vbNewLine & _
"<img src='cid:subs.jpg'" & "width='274' height='51'>"
With OutMail
.SentOnBehalfOfName = "newsuppliers#hewden.co.uk"
.To = "mark.o'brien#hewden.co.uk"
.CC = ""
.BCC = ""
.Subject = "(Credit Reference) New Supplier Credit Check - Reference: " & finalString4
.Attachments.Add TempFilePath & "cover.jpg", olByValue, 0
.Attachments.Add TempFilePath & "subs.jpg", olByValue, 0
.HtmlBody = strbody
'You can add a file like this
'.Attachments.Add ("C:\test.txt")
.Send 'or use .Display
End With
End If
End If
End If
End If
Next
I dont see save and close lines in your code. Try something like:
excWks4.Save
excWks4.Close
You may need to declare excWks4 like Workbook istead of Object.
Dim excWks4 as Workbook