Procedure not automatically generating number as coded - vb.net

My code is:
Private Function CreateID() As Integer
'finds the current highest ID
For Each row As DataRow In MedDT.Rows
If row.Item("MedicineID") > CreateID Then
CreateID = row.Item("MedicineID")
End If
Next
'returns a value for eventID that is unused as its higher then the current highest
Return CreateID
End Function
It should automatically generate a number which is one higher than the highest value in the DataTable but for some reason it isn't working
I call the procedure in the Form_Load procedure to fill a text box.

You are scanning a DataSet for the highest MedicineID number but you forgot to increment that value by 1 before returning, just change your return statement to:
Return CreateID + 1
You should just mark the ID column as IDENTITY and forget about that trivial thing though

Just to add to what Machinarius has said, Data Table itself has an auto Increment option on a column
DataColumn.AutoIncrement = true;
DataColumn.AutoIncrementSeed = 1;
DataColumn.AutoIncrementStep = 1;
so if you are not loading the data from a database you could also use this option.

Related

How to implement CHANGE_TRACKING_IS_COLUMN_IN_MASK in my application?

When working with Change Tracking in SQL Server, you're supposed to use CHANGE_TRACKING_IS_COLUMN_IN_MASK to determine which column was changed when dealing with updates. For example, like so:
DECLARE #last_synchronization_version bigint = ...;
DECLARE #column_id int = ...;
-- The statement below returns 1 if the specified column (#column_id) was changed, otherwise 0.
SELECT CHANGE_TRACKING_IS_COLUMN_IN_MASK(#column_id, SYS_CHANGE_COLUMNS)
FROM CHANGETABLE(CHANGES dbo.MyTable, #last_synchronization_version) AS CT
I wonder, is there a way to implement CHANGE_TRACKING_IS_COLUMN_IN_MASK myself, so I can work with the value of SYS_CHANGE_COLUMNS in my application without having to know beforehand which columns my application is interested in when executing the query?
For example, when I only change the value of the column with ID 11, the value of SYS_CHANGE_COLUMNS is 0x000000000B000000.
How can I programmatically determine that this mask contains the information that column 11 was changed?
It turns out SYS_CHANGE_COLUMNS consists of a byte array that can be grouped into groups of 4 bytes. The more columns were changed, the longer the byte array will be, thus the more groups you can make. The first byte of each group represents an ID of a column that was changed. In all of my tests, the other 3 bytes of each group were empty (0). I assume these bytes will be used when you have a column ID larger than 255. It seems the order in which columns were changed determines the order in which they appear in the byte array. Also, the first group of 4 bytes will always be empty (0), I'm not sure why.
To use this in application code, all you need to do is get a mapping for each column name and it's respective column ID. The previous paragraph should explain how to use SYS_CHANGE_COLUMNS to determine which column ID appears in the byte array.
C# example:
public static IEnumerable<int> GetColumnIdsInMask(byte[] columns)
{
// TODO: deal with column IDs larger than 255
for (var i = 4; i < columns.Length; i += 4)
{
yield return columns[i];
}
}
public static bool IsColumnInMask(int columnId, byte[] columns)
{
return GetColumnIdsInMask.Any(x => x == columnId);
}

Error iterating a Multi Value Parameter in SSRS Custom Code

I have a Multi value parameter in SSRS 2016 populated by a dataset. I have set the parameter properties as follows Data type 'Date/time', 'Allow multiple values', visibility is Internal and I've pointed Available and Default values to my dataset which is a simple select query returning dates. Using a for loop in custom code, I want to check if a given date is equal to any of the dates in the parameter. Whenever I use the index in the For Loop to index the parameter value I get #Error however
when I hard code the index with a any number I get the desired result
While (dt < endDate)
For i As Integer = 0 To Report.Parameters!parameter.Count()
If Report.Parameters!parameter.Value(i) = dt Then
count = count +1
Exit For
End If
Next i
dt = dt.AddDays(1)
End While
I expect 1 to be added count every time there's a match

SQL: Replacing dates contained within a text string

I am using SQL Server Management Studio 2012. I work with medical records and need to de-identify reports. The reports are structured in a table with columns Report_Date, Report_Subject, Report_Text, etc... The string I need to update is in report_text and there are ~700,000 records.
So if I have:
"patient had an EKG on 04/09/2012"
I need to replace that with:
"patient had an EKG on [DEIDENTIFIED]"
I tried
UPDATE table
SET Report_Text = REPLACE(Report_Text, '____/___/____', '[DEIDENTIFED]')
because I need to replace anything in there that looks like a date, and it runs but doesn't actually replace anything, because apparently I can't use the _ wildcard in this command.
Any recommendations on this? Advance thanks!
You can use PATINDEX to find the location of Date and then use SUBSTRING and REPLACE to replace the dates.
Since there may be multiple dates in the Text you have to run a while loop to replace all the dates.
Below sql will work for all dates in the form of MM/DD/YYYY
WHILE EXISTS( SELECT 1 FROM dbo.MyTable WHERE PATINDEX('%[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]%',Report_Text) > 0 )
BEGIN
UPDATE t
SET Report_Text = REPLACE(Report_Text, DateToBeReplaced, '[DEIDENTIFIED]')
FROM ( SELECT * ,
SUBSTRING(Report_Text,PATINDEX('%[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]%',Report_Text), 10) AS DateToBeReplaced
FROM dbo.MyTable AS a
WHERE PATINDEX('%[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]%',Report_Text) > 0
) AS t
END
I have tested the above sql on a dummy table with few rows.I don't know how it will scale for your data but recommend you to give it a try.
To keep it simple, assume that a number represents an identifying element in the string so look for the position of the first number in the string and the position of the last number in the string. Not sure if this will apply to your entire set of records but here is the code ...
I created two test strings ... the one you supplied and one with the date at the beginning of the string.
Declare #tstString varchar(100)
Set #tstString = 'patient had an EKG on 04/09/2012'
Set #tstString = '04/09/2012 EKG for patient'
Select #tstString
-- Calculate 1st Occurrence of a Number
,PATINDEX('%[0-9]%',#tstString)
-- Calculate last Occurrence of a Number
,LEN(#tstString) - PATINDEX('%[0-9]%',REVERSE(#tstString))
,CASE
-- No numbers in the string, return the string
WHEN PATINDEX('%[0-9]%',#tstString) = 0 THEN #tstString
-- Number is the first character to find the last position and remove front
WHEN PATINDEX('%[0-9]%',#tstString) = 1 THEN
CONCAT('[DEIDENTIFIED]',SUBSTRING(#tstString, LEN(#tstString)-PATINDEX('%[0-9]%',REVERSE(#tstString))+2,LEN(#tstString)))
-- Just select string up to the first number
ELSE CONCAT(SUBSTRING(#tstString,1,PATINDEX('%[0-9]%',#tstString)-1),'[DEIDENTIFIED]')
END AS 'newString'
As you can see, this is messy in SQL.
I would rather achieve this with a parser service and move the data with SSIS and call the service.

Incrementing the value of a variable by one

Incrementing the value of a variable by one is often achieved in other basic dialects in ways like
myreallylongandawkwardvariable ++
or
inc(myreallylongandawkwardvariable)
Is the only way to achieve this in VBA to code like this?
myreallylongandawkwardvariable = myreallylongandawkwardvariable +1
That is the only standard way to increment a variable with VBA.
If you really want to, you can create a custom procedure:
Sub Increment(ByRef var, Optional amount = 1)
var = var + amount
End Sub
Then you can do the following:
Increment myreallylongandawkwardvariable 'Increment by 1
Increment myreallylongandawkwardvariable, 5 'Increment by 5
#DanBaeckström, that is Not strictly correct.
If you call a procedure simply by its name, as in:
Increment myreallylongandawkwardvariable
you don't use parentheses.
But, if you precede this procedure call with the keyword "Call", as in:
Call Increment(myreallylongandawkwardvariable)
you MUST use parentheses.

How to exclude one value from a grouping sum, based on a value of another field?

How do I exclude one value from a grouping sum, based on a value of another field?
ie I open Report=> Report Properties=>Code and insert my Custom Code, but how would I change the below code to exclude a numeric value of another field for the below case?
Public Function ChangeWord(ByVal s As String) As String
Dim strBuilder As New System.Text.StringBuilder(s)
If s.Contains("Others") Then
strBuilder.Replace("Others", "Other NOT INCL")
Return strBuilder.ToString()
Else : Return s
End If
End Function
I'm assuming you want to exclude a numeric value from a sum where the string value of a cell on the same row includes "Others", and that the function you've supplied is used as the grouping criteria for a table in the report. Apologies if this isn't correct.
It's not going to be possible to do this without using a second piece of logic, either a function or an Iif condition. I don't have SSRS available to test this at the moment, but (assuming your value column is an integer, the code will look something like:
Public Function ExcludeOthers(rowDesc As String, rowVal as integer)
if ChangeWord(rowDesc) = "Other NOT INCL"
Return 0
else
Return rowVal
end if
End Function
Then, in the cell where you want the conditional sum to appear:
=Sum(ExcludeOthers(Fields!desc.Value,Fields!val.Value))
Alternatively, you could do this without the function by using Iif in the cell where the conditional sum will appear:
=Sum(Iif(ChangeWord(Fields!desc.Value) = "Other NOT INCL",0,Fields!desc.Value))
Depending on the nature of your source data, you could also do this by adding calculated columns to the report's source query.
I would favour the second or third option - custom code seems like overkill for this purpose.