I have an Access database which contains records that have a column "Team".
This column contains the Active Directory object "office" However, this column is not always correct.
Team
Info
ABC1
This team does not exist in AD
IT3
This team exists in AD
...
...
I want to check the column "team" of every record against the active directory, to get only the records, that have a valid team.
How can I achieve this in VBA?
I got a regex function to work in VBA, to check every record against a regular expression, however I'm not able to translate that to Active Directory related code snippets.
Option Compare Database
Option Explicit
Function regexp(StringToCheck As Variant, SearchPattern As String, Optional CaseSensitive As Boolean = True)
Dim re As New regexp
re.Pattern = SearchPattern
re.Global = False
re.IgnoreCase = Not CaseSensitive
Dim m
For Each m In re.Execute(StringToCheck)
regexp = m.Value
Next
End Function
I'm even stuck at looping just the input string itself through a loop like this, before I get further to the A issue:
Option Compare Database
Option Explicit
Function checkTeam(StringToCheck As String)
Dim team as String
Dim m
For Each m In StringToCheck
team = m.Value
Next
End Function
Related
I have a customers table that is displayed in a datagridview. I would like the user to be able to enter the customers full or partial last name and click a buttom that would then find the first customer that met the match in the text box. As an example: The user types "wil" into the text box and the first record found is for "williams" even though the user is looking for "wilson". The record would be highlighted(selected) and the user could scroll to look at other records and select "wilson" manually (the manual part I can code).
I have searched for hours on the internet and cannot find this type of code. Most of it is filtering or searching every cell and returning every value.
I am currently reworking a project I did with an access database and vba several years ago. I had thought vb.net would be very similar but it is not similar enough for me to modify this code. I'm also going to use a sql database.
The index field is obviously cell(0) and last name is cell(1).
I have found a solution although I did have to modify it. It will do everything I need except one thing. If I type the letter "H" and do a search on last name, it finds the first lastname that has an "H" in the last name but in a different position from the first letter. I need it to go to the first last name that begins with an "H". I have listed my code below.
Dim srch As String
Dim irowindex As Integer
Dim strl As Integer
srch = txtSearch.Text
dgvCustomers.ClearSelection()
For i As Integer = 0 To dgvCustomers.Rows.Count - 1
If dgvCustomers.Rows(i).Cells(0).Value IsNot Nothing Then
If dgvCustomers.Rows(i).Cells(1).Value.ToString.ToUpper.Contains(srch.ToUpper) Then
dgvCustomers.Rows(i).Selected = True
dgvCustomers.RowsDefaultCellStyle.SelectionBackColor = Color.DimGray
irowindex = dgvCustomers.SelectedCells.Item(0).Value
MessageBox.Show(irowindex)
Exit For
End If
End If
Next
End Sub
try this sir.
for each row as datagridviewrow in nameofdatagrid.rows
if row.cells("Lastname").value = txtbox.text then
nameofdatagrid.clearselection()
row.cells("Lastname").selected = true
exit for
end if
next
I think this is your problem? finding lastname match in the datagrid and select it?
hope this will help you :)
Dim srch As String
Dim irowindex As Integer
Dim strl As Integer
srch = txtSearch.Text
dgvCustomers.ClearSelection()
For i As Integer = 0 To dgvCustomers.Rows.Count - 1
If dgvCustomers.Rows(i).Cells(0).Value IsNot Nothing Then
If dgvCustomers.Rows(i).Cells(1).Value.ToString.ToUpper.StartsWith(srch.ToUpper) Then
dgvCustomers.Rows(i).Selected = True
dgvCustomers.RowsDefaultCellStyle.SelectionBackColor = Color.DimGray
irowindex = dgvCustomers.SelectedCells.Item(0).Value
MessageBox.Show(irowindex)
Exit For
End If
End If
Next
I built a sub that iterates over a sheet of business transactions for the day and addresses and attaches PDF receipts for our customers. Some customers work for the same firm, but are treated as different entities so they each receive their own email receipts. Folks from this particular firm are only identifiable as a team by their email handle, which is how I have been matching what receipts go to which email handles for which individuals.
Problem:
The problem I've encountered is that in the contacts master list (holds all of the contact information) the names are listed as first name then last name (I.E. John Snow) and on the occasion one of the external systems that information is pulled from lists the names as Last name then first name (Snow John), which isn't found by my current code. I know I could probably use InStr but to me that's a bit sloppy and the information contained in these receipts are extremely confidential. I'm struggling to come up with an consistent way to find the name regardless in a neat and eloquent way.
Possible solution I thought of was to split the names and store them into an array and then compare the different index places, but that seems inefficient. Any thoughts?
Current Code that is insufficient Note: This is only a small function from the main routine
Private Function IsEmpSameFirm(empName As String, firmEmail As String, firmName As String) As Boolean
'Finds separate employee email and compares to current email to find if same distribution
Dim empFinder As Range, firmFinder As Range
Dim columnCounter As Long
columnCounter = 1
While firmFinder Is Nothing
Set firmFinder = contactsMaster.Columns(columnCounter).Find(firmName)
columnCounter = columnCounter + 1
Wend
Set empFinder = contactsMaster.Rows(firmFinder.Row).Find(empName)
If empFinder Is Nothing Then
IsEmpSameFirm = False
ElseIf empFinder.Offset(0, 1).Value = firmEmail Then
IsEmpSameFirm = True
Else
IsEmpSameFirm = False
End If
End Function
Short answer: It is not possible
Middle answer: This implies a reasoning:
- You loop through your memories to recall which of the 2 gaven "Strings" is a name and which one is a last name. If you wish the PC to do the same, you'd need to "teach" it that -write a DataBase which contains every last name you know and if it's found there then it's a last name-
Long Answer:
What I'd do is split the text in columns, do a filter for each one and then analyze them "manually", this function may help you to split the string
Function RetriveText(InString As String, ChrToDivide, Position As Long)
On Error GoTo Err01RetriveText
RetriveText = Trim(Split(InString, ChrToDivide)(Position - 1))
If 1 = 2 Then '99 If error
Err01RetriveText: RetriveText = "Position " & Position & " is not found in the text " & InString
End If '99 If error
End Function
IE:
A1 =John Smith
B1 =RetriveText(A1," ",1) 'Result: John
C1 =RetriveText(A1," ",2) 'Result: Smith
Edit: Just realized that you are trying to send by email, are they contacts in Outlook? If so, why not to check them there? Try this function
Public Function ResolveDisplayName(sFromName) As Boolean
'----------------------------------------------------------------------------------
' Procedure : ResolveDisplayNameToSMTP
' Author : Sue Mosher - updated by D.Bartrup-Cook to work in Excel late binding.
'-----------------------------------------------------------------------------------
Dim olApp As Object 'Outlook.Application
Dim oRecip As Object 'Outlook.Recipient
Dim oEU As Object 'Outlook.ExchangeUser
Dim oEDL As Object 'Outlook.ExchangeDistributionList
Set olApp = CreateObject("Outlook.Application")
Set oRecip = olApp.Session.CreateRecipient(sFromName)
oRecip.Resolve
If oRecip.Resolved Then
ResolveDisplayName = True
Else
ResolveDisplayName = False
End If
End Function
In an Excel VBA module I'm building, I have some code to execute if a table of out-of-gauge cargo contains anything. I initially wrote this:
If Not IsEmpty(Range("OOGData")) Then
...
Else
...
End If
But even when OOGData is empty, it keeps returning False. I've tried it with If IsEmpty(Range("OOGData")) = False Then` but that doesn't seem to make any difference. My current code is
If IsEmpty(Range("OOGData")) = False Then
...but that still activates with the empty range.
I've made sure there are no formulae, hidden values or anything that could be showing up.
Any idea what the problem could be?
According to this information:
Returns a Boolean value indicating whether a variable has been
initialized.
In your code you are not working with variable therefore you shouldn't expect correct value.
When checking single cell you should use Len() function instead:
If Len(Range("OOGData"))=0 Then
'cell is empty
When checking if range of cells is empty use this solution:
If WorksheetFunction.CountA(Range("OOGData"))=0 Then
'rabge is empty
The final alternative I can think of is to use loops.
I've decided to cheat. Instead of checking the list there, I've added a Boolean variable (bContainsOOG) that's set to True any time an OOG cargo item is added to the OOG list, and then the reporting sub checks against that instead. But thanks both of you for those suggestions, they'll come in handy in another bit I was getting stuck on. :-)
This is a function that I thinks very closely fits:-
' Function to determine the last (first blank/null/empty) cell in a series of data in either a column
' or row
' Usage :- DataSeriesEnd(w,r,b)
' where w is the name of the worksheet.
' r is the row or column as an integer
' b is a boolean (true/false) if true then processing a column, if false a row
Public Function DataSeriesEnd(Worksheet As String, rc_index As Integer, bycolumn As Boolean) As Integer
Dim cv As Variant
For DataSeriesEnd = 1 To 500
If bycolumn Then
cv = Worksheets(Worksheet).Cells(DataSeriesEnd, rc_index)
Else
cv = Worksheets(Worksheet).Cells(rc_index, DataSeriesEnd)
End If
If IsNull(cv) Or IsEmpty(cv) Or cv = "" Then Exit For
Next DataSeriesEnd
' Position to previous cell (i.e. this one is empty)
DataSeriesEnd = DataSeriesEnd - 1
End Function
Note! There is a limit of 500 rows/columns
I'm building an application in VB.NET where I am pushing data from one database to another. The source database is SQL Server and the target is MySQL.
What I am doing is first creating DataTables for each table in each database which I use to do a comparison. I've written the queries in such a way so that the source and target DataTables contain exactly the same columns and values to make the comparison easier.
This side of the application works fine. What I do next is find rows which do not exist in the target database by finding PKs which do not exist. I then insert these new rows into the target database with no problem.
The Problem
What I now need to do is find rows in each table that have been updated, i.e. are not identical to the corresponding rows in the target DataTable. I have tried using Except() as per the example below:
Public Function GetUpdates(ByVal DSDataSet As MSSQLQuery, ByVal AADataSet As MySQLQuery, Optional ByVal PK As String = Nothing) As List(Of DataRow)
' Determines records to be updated in the AADB and returns list of new Rows
' Param DSDataSet - MSSQLQuery Object for source table
' Param AADataSet - MySQLQuery Object for destination table
' Optional Param PK - String of name common columns to treat as PK
' Returns List(Of DataRow) containing rows to update in table
Dim orig = DSDataSet.GetDataset()
Dim origTable = orig.Tables(0).AsEnumerable()
Dim destination = AADataSet.GetDataset()
Dim destinationTable = destination.Tables(0).AsEnumerable()
' Get Records which are not in destination table
Dim ChangedRows = Nothing
If IsNothing(PK) Then
ChangedRows = destinationTable.AsEnumerable().Except(origTable.AsEnumerable(), DataRowComparer.Default)
End If
Dim List As New List(Of DataRow)
For Each addRow In ChangedRows
List.Add(addRow)
Next
Return List
End Function
The trouble is that it ends up simply returning the entire set of source rows.
How can I check for these changed rows? I could always hardcode queries to return what I want but this introduces problems because I need to make comparisons for 15 tables so it would be a complete mess.
Ideally I need a solution where it will take into account the variable number columns from the source tables for comparison against what is essentially an identical target table and simply compare the DataRows for equality.
There should be a corresponding row in the target tables for every source row since the addition of new rows is performed prior to this check for updated rows.
I am also open to using methods other than LINQ to achieve this.
Solution
In the end I implemented a custom comparer to use in the query as shown below. It first checks if the first column value matches (PK in my case) where if it does then it we check column-wise that everything matches.
Any discrepancy will set the flag value to FALSE which we return. If there aren't any issues then TRUE will be returned. In this case I used = to compare equality between values rather than Equals() since I'm not concerned about a strict equality.
The resulting set of DataRows is used to UPDATE the database using the first column value (PK) in the WHERE clause.
Imports System.Data
Class MyDataRowComparer
Inherits EqualityComparer(Of DataRow)
Public Overloads Overrides Function Equals(x As DataRow, y As DataRow) As Boolean
If x.Item(0).ToString().Equals(y.Item(0).ToString()) Then
' If PK matches then check column-wise.
Dim Flag As Boolean = True
For Counter As Integer = 0 To x.ItemArray.Count - 1
If Not x.Item(Counter) = y.Item(Counter) Then
Flag = False
End If
Next
Return Flag
Else
' Otherwise don't bother and just skip.
Return False
End If
End Function
...
End Class
class MyDataRowComparer : IEqualityComparer<DataRow>
{
public bool Equals(DataRow x, DataRow y)
{
return x["ColumnName"].Equals(y["ColumnName"]);
// Can add more columns to the Comparison
}
public int GetHashCode(DataRow obj)
{
return obj["ColumnName"].GetHashCode();
// Can add more columns to calculate HashCode
}
}
Now the Except statement will be like:
ChangedRows = destinationTable.AsEnumerable()
.Except(origTable.AsEnumerable(), MyDataRowComparer)
I have two data set in my code. I need to compare that second data set
with first data set My first data set returns this result below:-
FirstDs:-
MaxUpdatedPrepped MaxUpdatedSent MaxUpdatedStamped
1900-01-01 1900-01-01 1900-01-01
And my second data set returns below:-
SecondDS:-
MaxUpdatedPrepped MaxUpdatedSent MaxUpdatedStamped
1900-01-01 1900-01-01 2014-11-11
I need to compare that both result and return alert like "Not matched" if the both first data set value is not match with second data set value. I tried a lot but i could get only wrong answer
For i As Integer = 0 To DsMaxDates1.Tables(0).Rows.Count - 1
Dim found As Boolean = False
For j As Integer = 0 To ds.Tables(0).Rows.Count - 1
If DsMaxDates1.Tables(0).Rows(i)(0).ToString = ds.Tables(0).Rows(j)(0).ToString Then
found = True
End If
Next
If found = False Then
ASPNET_MsgBox("Another User Working in Same Account. Please Click Reset.")
End If
Next
This above result returns true instead of false.
You should never change the type of your data unless it's absolutely necessary. Treat dates as Date, integers as Integer, strings as String, decimals as Decimal, etc. The ToString method is mostly used when you want to display the data to the user.
With that being said, you're not comparing datasets, you're comparing datatables.
The reason as to why it returns True is because you only compare the first column. You need to compare all the columns. If your table doesn't contain complex data types like byte arrays then the simplest way is to use LINQ combined with Enumerable.SequenceEqual.
The following code assumes that each table contains the same number of rows and columns.
''Uncomment to unleash the one-liner:
'Dim notEqual As Boolean = (From i As Integer In Enumerable.Range(0, DsMaxDates1.Tables(0).Rows.Count) Where (Not DsMaxDates1.Tables(0).Rows(i).ItemArray.SequenceEqual(ds.Tables(0).Rows(i).ItemArray)) Select True).FirstOrDefault()
Dim notEqual As Boolean = (
From i As Integer In Enumerable.Range(0, DsMaxDates1.Tables(0).Rows.Count)
Where (Not DsMaxDates1.Tables(0).Rows(i).ItemArray.SequenceEqual(ds.Tables(0).Rows(i).ItemArray))
Select True
).FirstOrDefault()
If (notEqual) Then
ASPNET_MsgBox("Another User Working in Same Account. Please Click Reset.")
End If
You can expand this even further by creating a reusable extension method:
Public Module Extensions
<System.Runtime.CompilerServices.Extension()>
Public Function SequenceEqual(table1 As DataTable, table2 As DataTable) As Boolean
Return (((((Not table1 Is Nothing) AndAlso (Not table2 Is Nothing))) AndAlso ((table1.Rows.Count = table2.Rows.Count) AndAlso (table1.Columns.Count = table2.Columns.Count))) AndAlso ((table1.Rows.Count = 0) OrElse (Not (From i As Integer In Enumerable.Range(0, table1.Rows.Count) Where (Not table1.Rows(i).ItemArray.SequenceEqual(table2.Rows(i).ItemArray)) Select True).FirstOrDefault())))
End Function
End Module
Then you can simply do as follows:
If (Not DsMaxDates1.Tables(0).SequenceEqual(ds.Tables(0))) Then
ASPNET_MsgBox("Another User Working in Same Account. Please Click Reset.")
End If