I want to do a date comparison to check whether is the Before Period is bigger than After Periode
So far it has been working properly until the date range is a bit tricky
For example
The value is from a dropdownlist item
Before period is 21-10-2022
After period is 04-11-2022
It will trigger the error message I set if the before period is bigger than the period after
I have a code like this
If CDate(ddlPeriodeBefore.SelectedValue) <= CDate(ddlPeriodeBefore.SelectedValue) Then
'Does the job if the the before period is smaller than after period
Else
lblInfo.Text = "Period BEFORE Must Be SMALLER Than Period AFTER."
End If
Can anyone help me? it keeps saying "conversion from string to date is not valid"
I've tried datetime.parse, parse exact, cdate, convert.todatetime but nothing works so far, or maybe I used it the wrong way
Please help, thanks in advance
Tim Schmelter's suggestion is not wrong, but I did want to provide an alternative. Create a collection of Tuple, add the dates (both formatted string and native value) to the collection, then bind the control to the list.
Here is the alternative:
Dim dates As New List(Of Tuple(Of String, DateTime))()
Dim today = DateTime.Today
For daysSubtract = 90 To 0 Step -1
Dim dateToAdd = today.AddDays(-daysSubtract)
dates.Add(New Tuple(Of String, DateTime)(dateToAdd.ToString("dd-MM-yyyy"), dateToAdd))
Next
ddlPeriodeBefore.ValueMember = "Item1"
ddlPeriodeBefore.DisplayMember = "Item2"
ddlPeriodeBefore.DataSource = dates
ddlPeriodeAfter.ValueMember = "Item1"
ddlPeriodeAfter.DisplayMember = "Item2"
ddlPeriodeAfter.DataSource = dates
Now when you go to get the selected value, you can use a simpler conversion since the stored object is already a DateTime:
Dim beforePeriod = DirectCast(ddlPeriodeBefore.SelectedValue, DateTime)
Dim afterPeriod = DirectCast(ddlPeriodeAfter.SelectedValue, DateTime)
If (beforePeriod <= afterPeriod) Then
' ...
Else
lblInfo.Text = "Period BEFORE Must Be SMALLER Than Period AFTER."
End If
The advantage to this approach is that you do not have to refactor your code if the date formatting changes.
If DateTime.Parse works depends on your curren culture because you don't pass any. For me this works fine (but for you not):
Dim selectedValue1 = "21-10-2022"
Dim selectedValue2 = "04-11-2022"
Dim beforePeriod = Date.Parse(selectedValue1)
Dim afterPeriod = Date.Parse(selectedValue2)
So either you know the correct culture that you have used when you have created this string, then you can pass this as second parameter to Date.Parse, or you use ParseExact:
Dim beforePeriod = Date.ParseExact(selectedValue1, "dd-MM-yyyy", CultureInfo.InvariantCulture)
Dim afterPeriod = Date.ParseExact(selectedValue2, "dd-MM-yyyy", CultureInfo.InvariantCulture)
The culture is relevant because they can have different date separators and the order of the day-, month- and year-tokens are different.
Related
The Primary function calling Day1WeekNum & Day1inMonth
Function NthDay(Date1)
' Tells you if a date is the 3rd Tuesday of the Month
Dim Day1Name, Day1WeekNum, A, B, DayName, Nth
Dim Status ' Tells you if there is anything in the rest of the Array
Dim cWeekNum ' Number for the current week
Dim WeekDiff 'Difference between the week numbers
Dim cDayNum 'Number for the day of the week for Date1
Dim Week1Num
Week1Num = Day1WeekNum(Date1) ' tells me the week number of the first day of the month
Day1Name = Day1inMonth(Date1) ' tell me the day of the week for the first day of the month
Code for Day1inMonth
Function Day1inMonth(Date1)
'Tells you the weekday of the first day in a month of the provided date
Dim cYear, cMonth, month1st, day1
cYear = Year(Date1)
cMonth = Month(Date1)
month1st = DateSerial(cYear, cMonth, 1)
day1 = Weekday(month1st, vbSunday)
Day1inMonth = day1
End Function
Code for Day1WeekNum
Function Day1WeekNum(Date1 As Date)
'Tells you the week of the first day of the month of the provided date
Dim cYear, cMonth, day1Week
Dim month1st As Date
cYear = Year(Date1)
cMonth = Month(Date1)
month1st = DateSerial(cYear, cMonth, 1)
day1Week = WorksheetFunction.WeekNum(month1st, 1)
Day1WeekNum = day1Week
End Function
I had to change the code above to the code below in order to stop a mismatch error. I don't know why. Does it have to relate to variable scope or something else? I'm trying to understand so I can avoid the reason for the error in the future.
New code that allowed it to work:
Function Day2WeekNum(Date1)
'Tells you the week of the first day of the month of the provided date
Dim cYear1, cMonth1, day1Week1
Dim month1st1 As Date
cYear1 = Year(Date1)
cMonth1 = Month(Date1)
month1st1 = DateSerial(cYear, cMonth, 1)
day1Week1 = WorksheetFunction.WeekNum(month1st, 1)
Day2WeekNum = day1Week1
End Function
You have both a local variable and a function in scope which have the same name - Day1WeekNum
The local variable is implicitly a Variant because it hasn't been declared as being of any specific type. Variants can contain arrays as well as individual (scalar) values.
The assignment Week1Num = Day1WeekNum(Date1) looks like a function call but is actually trying to access an array. No array has been defined so you get a type mismatch error. If you give the Week1Num variable an explicit non-array/non-Variant type then the error will change to "Compile error: expected array".
Changing the function name worked because the new function name didn't match any local variables in the calling procedure. To avoid this issue in future:
use Option Explicit at the top of each module (by turning on
"Require Variable Declaration" in Tools > Options > Editor in the VBA
editor)
give every variable an explicit type - e.g. Dim Day1WeekNum As Integer
avoid declaring variables which have the same name as a sub or function that is in scope because this can be confusing and lead to issues
I'm currently using the domino desginer 8.5.2 and I encountered a strange thing related to the notesdocument Created property.
I'm trying to create an agent in lotusscript that selects some documents based on their Created date.
I have the following test code where doc is a NotesDocument in a specific NotesDatabase:
If doc.Created < DateNumber(1951,1,1) Then
Print "old"
End If
The issue is that there are no documents in the DB that are older than 2010 yet the code above Prints "old" for some documents (like 10 in 5k), but when I enter the debugging session and check the doc's Created property in the Variables window it's a normal date like 2012. 02. 03. or smth.
Another interesting note is that if I try to write the Created date into a csv file it's a nonsense date like 1896. 06. 20. but then again when I check the property while debugging it's completely normal.
Have you encountered this issue before? Or am I comparing dates in the wrong way?
----EDIT1------------
I oversimplified the question, I'm really sorry if it was misleading I can only humbly ask you to keep the ideas comming because solving this issue is crucial.
The agent in question does not process it's own documents, it's opening multiple databases on the server (a lot of ppl's mail databases) and processing documents (emails) by multiple conditions. What we actually do is this:
strFileName = "D:\temp\log.csv"
Set nStream = session.CreateStream()
nStream.Open(strFileName)
nStream.Truncate
Dim deleteCutoffDate As New NotesDateTime("Today")
Dim moveCutoffDate As New NotesDateTime("Today")
Dim tmp As Integer
tmp = settingsDto.GetDeleteOlderThanMonths()
Call deleteCutoffDate.Adjustmonth((-1)*tmp, True)
searchForm$ = {Form = "Memo" }
Set doccol = db.Search(searchForm, Nothing, 0) 'db is an opened NotesDatabase
Set doc = doccol.GetFirstDocument
While Not doc Is Nothing
Dim nextDoc As NotesDocument
Set nextDoc = doccol.Getnextdocument(doc)
'Earlier condition we tried
'If doc.Created < deleteCutOffDate.Lslocaltime
' deleteCutoffDate is today - 3 years
If (Fix( doc.Created ) < Fix( CDat(deleteCutoffDate.Dateonly))) Then
'Suggested solution to check dates
Dim longTemp As Long
longTemp = Fix( CDat(deleteCutoffDate.Dateonly)) 'should be 36,647 (#days from Dec 30, 1899 to May 1, 2000)
longTemp = Fix( doc.Created ) 'check this number makes sense (see last line)!
'This is only for logging, testing.
Dim temp As String
temp = Format( doc.Created, "yyyy-mm-dd")+";"+doc.Noteid+";"
Call nStream.WriteText(temp,EOL_PLATFORM)
'******* Processing logic goes here **********
End If
Set doc = nextDoc
Wend
Call nStream.Close()
So the problem and the symptoms I saw so far:
Some documents (always the same) have weird Creation dates. Let's say we have 3 documents A, B, C.
When I write document A's Created property to csv it says 1899-12-30 when I check the debugger the doc.Created is 2015-01-06 which is the correct date but Fix( doc.Created ) is 0. This makes no sense. This sould not pass the if condition and be written into csv acording to Fix beeing 0 yet is does.
Document B's date is 1899 in csv, debugger says 2015-10-25, Fix( doc.Created ) reports the correct number BUT this document should not have gone through the If condition since the if only allows a pass for documents older than 3 years starting from today. So if i run the script on '18-02-07 documents created before 15-02-07 should pass the condition.
Document C's date is 4916-04-18 everything else is the same as above
These issues apper on multiple (but always on the same) documents. But these are not special documents or anyting they are simple emails
Another thing I noticed is if I run the script multiple times in a row (without debugging or interfering) sometimes the CSV reports the correct dates! For me this suggests some sort of a reference issue but at this point i'm not sure how the world works.
Note that there are no other processing logic is involved, all the logic inside the If condition have been commented out that manipulated the documents. Test database has been restored to it's original state
If you have any ideas please don't hold back I am stuck on this issue for days now.
Thanks
It looks like what you are trying to do should work fine. I think the created date comes from a part of the doc universal id, so if that was set programatically it would be possible to see docs with creation dates that looked very old.
I would suggest trying the following to see if you can spot where the issue is
dim longTemp as long
dateTemp = cdat( "May 1, 2000" )
longTemp = Fix( dateTemp ) 'should be 36,647 (#days from Dec 30, 1899 to May 1, 2000)
longTemp = Fix( doc.Created ) 'check this number makes sense (see last line)!
If doc.Created < dateTemp then
print "old"
end if
Re writing doc.created to a csv file, I would suggest formatting it as text before writing, so
format( doc.created, "yyyy-mm-dd") 'or your preferred date format
I give up. Time to punt and suggest workarounds! Might any of these work?
Workaround 1: Formulas
Instead of an if block, build the date criteria within the search formula for doccol. This is probably faster anyway.
strFileName = "D:\temp\log.csv"
Set nStream = session.CreateStream()
nStream.Open(strFileName)
nStream.Truncate
Dim deleteCutoffDate As New NotesDateTime("Today")
Dim moveCutoffDate As New NotesDateTime("Today")
Dim tmp As Integer
tmp = settingsDto.GetDeleteOlderThanMonths()
Call deleteCutoffDate.Adjustmonth((-1)*tmp, True)
searchForm$ = {Form = "Memo" & #Created < [} + deleteCutoffDate.LocalTime + {]} '<--- removed if block and put criteria checking here
Set doccol = db.Search(searchForm, Nothing, 0) 'db is an opened NotesDatabase
Set doc = doccol.GetFirstDocument
While Not doc Is Nothing
Dim nextDoc As NotesDocument
Set nextDoc = doccol.Getnextdocument(doc)
'Earlier condition we tried
'If doc.Created < deleteCutOffDate.Lslocaltime
' deleteCutoffDate is today - 3 years
'Suggested solution to check dates
Dim longTemp As Long
longTemp = Fix( CDat(deleteCutoffDate.Dateonly)) 'should be 36,647 (#days from Dec 30, 1899 to May 1, 2000)
longTemp = Fix( doc.Created ) 'check this number makes sense (see last line)!
'This is only for logging, testing.
Dim temp As String
temp = Format( doc.Created, "yyyy-mm-dd")+";"+doc.Noteid+";"
Call nStream.WriteText(temp,EOL_PLATFORM)
'******* Processing logic goes here **********
Set doc = nextDoc
Wend
Call nStream.Close()
Workaround 2: Filter through NotesDateTime?
Maybe this would work?
strFileName = "D:\temp\log.csv"
Set nStream = session.CreateStream()
nStream.Open(strFileName)
nStream.Truncate
Dim deleteCutoffDate As New NotesDateTime("Today")
Dim moveCutoffDate As New NotesDateTime("Today")
Dim createdDate As NotesDateTime '<----
Dim tmp As Integer
tmp = settingsDto.GetDeleteOlderThanMonths()
Call deleteCutoffDate.Adjustmonth((-1)*tmp, True)
Call deleteCutoffDate.SetAnyTime '<----
searchForm$ = {Form = "Memo" }
Set doccol = db.Search(searchForm, Nothing, 0) 'db is an opened NotesDatabase
Set doc = doccol.GetFirstDocument
While Not doc Is Nothing
Dim nextDoc As NotesDocument
Set nextDoc = doccol.Getnextdocument(doc)
'Earlier condition we tried
'If doc.Created < deleteCutOffDate.Lslocaltime
' deleteCutoffDate is today - 3 years
'Your current condition
'If (Fix( doc.Created ) < Fix( CDat(deleteCutoffDate.Dateonly))) Then
Set createdDate = New NotesDateTime(doc.Created) '<----
Call createdDate.SetAnyTime '<----
If createdDate.TimeDifference(deleteCutoffDate) < 0 Then '<----
'Suggested solution to check dates
Dim longTemp As Long
longTemp = Fix( CDat(deleteCutoffDate.Dateonly)) 'should be 36,647 (#days from Dec 30, 1899 to May 1, 2000)
longTemp = Fix( doc.Created ) 'check this number makes sense (see last line)!
'This is only for logging, testing.
Dim temp As String
temp = Format( doc.Created, "yyyy-mm-dd")+";"+doc.Noteid+";"
Call nStream.WriteText(temp,EOL_PLATFORM)
'******* Processing logic goes here **********
End If
Set doc = nextDoc
Wend
Call nStream.Close()
Workaround 3: Sanity filter
Add a function that checks and uses #Formulas if LotusScript fails, because while slower, hopefully that works
Function fdtSaneDocCreated(doc As NotesDocument) As Variant 'Dateonly
Const ciMinDate = 40179 'CLng(CDat("1/1/2010"))
Const ciMaxDate = 51136 'CLng(CDat("1/1/2040"))
fdtSaneDocCreated = doc.Created
If fdtSaneDocCreated < ciMinDate Or fdtSaneDocCreated > ciMaxDate Then
'This is slower, but AT LEAST IT WORKS! (... hopefully)
Dim array As Variant
array = Evaluate({#Created}, doc)
fdtSaneDocCreated = array(0)
If fdtSaneDocCreated < ciMinDate Or fdtSaneDocCreated > ciMaxDate Then
Error 1, "This workaround doesn't work for " + doc.NotesURL
End If
End If
End Function
and then change your code by replacing doc.Created with fdtSaneDocCreated(doc)
Sorry for the long silence I really needed to catch up with this project.
First of all thank you all for contributing to this thread all of your answers added a puzze piece to the picture.
So the problem was that the doc.Created reported wrong dates. Following your posts I red the following documentation.
http://www-01.ibm.com/support/docview.wss?uid=swg21111786
According to the link above a documents Created date is determined by the OID.
So there is this:
http://www-12.lotus.com/ldd/doc/domino_notes/9.0/api90ug.nsf/85255d56004d2bfd85255b1800631684/00d000c1005800c985255e0e00726863?OpenDocument
This link explains how the OID works and how it should look.
I checked the OID with NotesPeek and bingo! OID should have contained a vaild date but instead It was complete gibberish like 9856.06.20. Sometimes the date part was simply missing, that's why I saw 1899.
The closing point of this issue was the following link which confirmed that this strange behavior is a bug of Notes 8.5.1
https://www-01.ibm.com/support/docview.wss?uid=swg1LO47325
Example, Online document: [removed link as no longer needed]
Which outputs:
Value1=1
Value2=5
The rest of this document would have random text to ignore.
I would like to search for Value1 and Value2, then output it's value [I need this to be expandable if I decide to add new information in the future]
[the output may be longer than one character, and might be text rather than a number]
Dim Value1Result as Integer = [value from online file] '1 in this case
Dim Value2Result as Integer = [value from online file] '5 in this case
Edit: Added logic to strip the version number. Very basic but as long as the format doesn't change it should work. You'll need to handle parsing to int, double, etc if you ever use "1.2" or whatever for a version.
If I understand your question correctly, you just need to download the file, store it in a local variable, and then do something with it. Comment if this is not the case and I will adjust.
I would do this by creating a WebClient, downloading the data, converting it to a string, and then operating on it. I did not add any headers - dropbox doesn't require it, but something to keep in mind for production... Small example below:
Dim bResult() As Byte
Dim sUrl As String = "https://dl.dropboxusercontent.com/s/bus2q71wsn9txuz/Test.txt?dl=0"
Using client As New WebClient
bResult = client.DownloadData(sUrl)
End Using
Dim retData As String = Encoding.UTF8.GetString(bResult)
Dim retList As List(Of String) = retData.Split(Environment.NewLine).ToList()
Dim sMin = retList(0).Split("=").Last()
Dim sNew = retList(1).Split("=").Last()
I am accessing a document from a view, read a datetime field, figure out number of days between two date/time values which fall into four categories. In each category there is a for loop which add number of datetime values to an array of variant. Array entries are between seven and 35. After the loop I like to assign the array values to a date time field on the form and save the document. I have used Notes item as follow:
Dim nitem as Notesitem
Set nitem = doc.ReplaceItemValue("Datefield", dtArray)
It didn't work. I used doc.ReplaceItemValue "Datefield, dtArray this one didn't work either. The field is blank after the agent runs. I declared a variable and assigned the array to the variable then assigned variable to the field on the form:
Dim var1 as variant
var1 = dtArray
doc.datefield = Var1
Still no luck to see array values assigned to the field in the document
Here is main loop
Redim dateArray(0)
For i=0 to NumberofDays -1
set notesitem = dtitem.DateTimeValue
call notesitem.AdjustDay(i)
set dateArray(i) = notesitem
Redim preserve dateArray(i+1)
Next
doc.replaceitemvalue "Datefield", dateArray
call doc.save(false, true)
erase dateArray
Why after the agent runs datefield in the documents are blank? What is missing? How should I change this to get result. Is it possible to add a delemiter to the assignment statement as follows:
Thank you
When you're playing around with NotesItem and the NotesDateTime classes, I think you will have more joy using the NotesItem DateTimeValue property. This is read / write, and returns (or expects) a NotesDateTime object.
For example, if you have a NotesDateTime instance called "dt", this is how you would write it back to a field called "YourDT":
Dim itDT as NotesItem
Dim dt as New NotesDateTime
' Instantiate itDT and dt
...
Set itDT.DateTimeValue = dt
So, you should be able to take your array of NotesDateTime objects, and write it back to the relevant field using this approach.
The simplest way to assign dateTime field from an array is:
SimpleDateFormat smdf = new SimpleDateFormat();
smdf.applyPattern("dd.MM.yyyy");
Vector dates = new Vector();
for (Date dt: dateArray) {
dates.addElement(smdf.formatter(dt));
};
doc.replaceItemValue("dateField", dates);
This is tricky to trouble shoot for you, as you haven't provided the original source code. The way your trying to use methods is a bit strange.
Below is a basic go at what you're trying to do. DateTime fields are a bit tricky, but you can set them using variant arrays.
Dim i As Integer
Dim vDateArr() As Variant
Dim itDate As notesItem
' setup date array.
' .........
' .........
' Now get the date field to be updated from the document
Set itDate = doc.GetFirstItem("fieldName")
' loop through the array of values and make sure they're date time
For i=0 To numberOfDays - 1
' ensure that the array has date type values. V_DATE is a constant defined
' in LSConst.lss. V_DATE = 7, so you can still write the following line as
' If Datatype(vDateArr(i)) <> 7 then
If Datatype(vDateArr(i)) <> V_DATE Then
vDate = Cdat(vDateArr(i))
End If
vDateArr(i) = vDate
Next
' assign the array back onto the itDate field. Even if the field is not
' already a dateTime type. Assigning the array this way will make it so.
itDate.Values = vDateArr
Call doc.Save(True, False)
I find it best to work with primitives, not objects in this case. What's happening here is that I am ensuring that the date values are stored as a dateTime value. Then assigning the array to the field and then saving the document. There are a number of ways to do this, but this is my preferred way when you want to push an array of a specific type into a field. If you can post the original code, it would be easier to correct your code.
I'm trying to use the current day in GetAllEntriesByKey by passing an array. The array so far looks like this
Dim keyarray(2) As Variant
keyarray(0) = "FF Thompson ADT"
Set keyarray(1) = dateTime
I would like to say this
Set vc = view.GetAllEntriesByKey(keyarray, False)
Here is a row of what it looks like when it works. The test agent prints out csv in an email.
FF Thompson ADT,2/3/2009,11:45:02 PM,0,6,0,,00:00:04,5400,4
I can't seem to pass a current day dateTime that runs. I can set the dateTime manually in the declaration and it works. I think it's because it's trying to also pass the time but I don't know. I have tried three ways and it says invalid key value type.
Dim dateTime As New NotesDateTime("")
Call dateTime.LSLocalTime = Now
...
keyarray(1) = dateTime.Dateonly
Dim dateTime As New NotesDateTime("")
Call dateTime.SetNow
...
keyarray(1) = dateTime.Dateonly
Dim dateTime As New NotesDateTime("Today")
...
keyarray(1) = dateTime.Dateonly
I don't know if this is useful but I read about Evaluate here.
What I'm ultimately trying to do is GetFirstEntry for "FF Thompson ADT" for the most recent day entries exist. I'm also trying to do the same for the day before that. I'm trying to sum up the files processed (the number 6) for both days and errors (the null) for the most recent day using something like this. I need to tweak it so it finds the files processed and errors for entries but I haven't gotten there but should be able to do. I'm also just trying to find the most recent date with time value for the feed ie "FF Thompson ADT".
Set entry = vc.GetFirstEntry
filesprocessed = 0
Dim errors, errortotal As Integer
errors = 0
errorstotal = 0
While Not entry Is Nothing
rowval = 0
errors = 0
Forall colval In entry.ColumnValues
If rowval > 0 Then
errors = Cint(colval)
Else
rowval = Cint(colval)
End If
End Forall
filesprocessed = filesprocessed + rowval
errorstotal = errorstotal + errors
Set entry = vc.GetNextEntry(entry)
Wend
Thanks for any help or suggestions. They are greatly appreciated.
I've only used the GetAllEntriesByKey method with an array of strings. I've never tried mixing types. But assuming differing types are valid for that method, the problem might lie in the difference between datetime types in Notes. There's a core LS datetime type and then there's a NotesDateTime object. I'd bet the view considers a date column to be made up of the core datetime types, and so it fails when you pass the NotesDateTime type.
But that issue aside, my suggestion is to create a view that has the columns you want to access, and set the sort order of the first column (containing FF Thompson ADT) to asc, then set the second column with your dates to desc. You can then access the view entries in the order you want, with the most recent being first, 2nd most recent 2nd, etc.
If by some chance the GetAllEntriesByKey method returns the documents out of order (I forget if it guarantees order), I know I've done this before using the NotesViewNavigator class. There's definitely an alternate way to do it without need to call GetAllEntriesByKey with the date key.
Here's an answer I found
Dim todaysdate As New NotesDateTime("Today")
Dim dateTime As New NotesDateTime(todaysdate.DateOnly)
Dim keyarray(1) As Variant keyarray(0) = feedname
Set keyarray(1) = dateTime
Set vc = view.GetAllEntriesByKey(keyarray, False)