l3ill Posted October 3, 2016 Posted October 3, 2016 (edited) Windows 7 Ultimate 64 Bit Keyboard and Language set to English Format and Location set to Germany Works like a charm I had the Jan 01 to Dec 31 problem when testing (changing region/language settings). You have to restart the script and then it works... p.s. I got an empty nth element on a couple of the first tests but it looks like they were also the jan01 to dec 31 ones.. one was 3 years so not only affected by short ranges... Edited October 3, 2016 by l3ill czardas 1 My Contributions... SnippetBrowser NewSciTE PathFinder Text File Manipulation FTP Connection Tester / INI File - Read, Write, Save & Load Example
czardas Posted October 3, 2016 Author Posted October 3, 2016 (edited) I think I know what is wrong with the MMDDYYYY order. It's a silly oversight on my part. The other issues don't make much sense to me right now. After I clean up the code, perhaps I'll discover something. One thing I would like to know is whether these empty array elements are an extra day added to the selected range, or the last day within the selected range. This clearly needs more work. Edited October 3, 2016 by czardas operator64 ArrayWorkshop
l3ill Posted October 3, 2016 Posted October 3, 2016 (edited) I was able to reproduce the empty nth element with the jan01 dec31 "bug". It only happens here when I set to US Format and Location settings. edit: location settings are irrelevant. US format clearly causes problems though... Restarting the script fixes the Jan Dec bug but not the nth element bug. Edited October 3, 2016 by l3ill My Contributions... SnippetBrowser NewSciTE PathFinder Text File Manipulation FTP Connection Tester / INI File - Read, Write, Save & Load Example
czardas Posted October 3, 2016 Author Posted October 3, 2016 Thanks that's very helpful. operator64 ArrayWorkshop
iamtheky Posted October 3, 2016 Posted October 3, 2016 1 hour ago, czardas said: You must have somehow only clicked the year or something. It could be the many pages of code, or it could be my ability to navigate a date control, and you went with the latter? It is getting late over there czardas 1 ,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-. |(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/ (_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_) | | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) ( | | | | |)| | \ / | | | | | |)| | `--. | |) \ | | `-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_| '-' '-' (__) (__) (_) (__)
czardas Posted October 3, 2016 Author Posted October 3, 2016 I have fixed the MMDDYYYY bug and updated the first post. I doubt that it has any connection to the other issues, but I need to test that. operator64 ArrayWorkshop
czardas Posted October 3, 2016 Author Posted October 3, 2016 (edited) 14 minutes ago, iamtheky said: It is getting late over there Time to eat and sleep - the wood for the trees. In other words, you're right. Edited October 3, 2016 by czardas operator64 ArrayWorkshop
Moderators JLogan3o13 Posted October 3, 2016 Moderators Posted October 3, 2016 Odd. Now when I put in a date beginning today and ending two weeks from now on the 17th, it gives me everything from the End Date to the end of the year. I deleted the old code, was it doing that before? "Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball How to get your question answered on this forum!
czardas Posted October 3, 2016 Author Posted October 3, 2016 (edited) I will have to look at it again tomorrow because I am too tired at the moment. It might be something to do with ArrayWorkshop.au3. However it could be something really simple like a bad regexp somewhere. Here's the earlier (more broken) version of the particular function which I updated in the first post. I have yet to try different language settings on my PC. The descriptions you have given me should be very helpful (much appreciated). It's very easy to miss a problem that hides itself away like this. expandcollapse popupFunc GetDateArray($sStartDate, $sStopDate, $sDelim = Default, $sFormat = Default, $iDayName = -1) Local $iID = _WinAPI_GetUserDefaultLCID(), _ $aDateSplit = StringRegExp(_WinAPI_GetLocaleInfo($iID, $LOCALE_SSHORTDATE), '\w+', 3) If IsArray($aDateSplit) And UBound($aDateSplit) = 3 Then For $i = 0 To 2 ; determine the locale ymd order If StringInStr($aDateSplit[$i], 'y') Then $aDateSplit[$i] = 1 ; year ElseIf StringInStr($aDateSplit[$i], 'm') Then $aDateSplit[$i] = 2 ; month ElseIf StringInStr($aDateSplit[$i], 'd') Then $aDateSplit[$i] = 3 ; day EndIf Next Else ; let's try an alternative method [both methods work on Win7 in the UK] Local $sLongDate = _WinAPI_GetDateFormat(0, 0, $DATE_LONGDATE) $aDateSplit = StringRegExp($sLongDate, '(*UCP)\w+', 3) If Not IsArray($aDateSplit) And UBound($aDateSplit) <> 3 Then Return SetError(1) ; undetermined error? For $i = 0 To 2 ; determine the locale ymd order If $aDateSplit[$i] = @YEAR Then ; hopefully this method will work for all international regions $aDateSplit[$i] = 1 ; year ElseIf $aDateSplit[$i] = _DateToMonth(@MON, $DMW_LOCALE_LONGNAME) Then $aDateSplit[$i] = 2 ; month Else $aDateSplit[$i] = 3 ; day EndIf Next EndIf ; check the array contains numbers 1 to 3 Local $sTest = $aDateSplit[0] & $aDateSplit[1] & $aDateSplit[2] If Not (StringInStr($sTest, '1') And StringInStr($sTest, '2') And StringInStr($sTest, '3')) Then Return SetError(2) ; undetermined error? If $sDelim = Default Then $sDelim = StringRegExp($sStartDate, '\D+', 3)[0] Local $iCount = 1, $sYMD = '' Do For $i = 0 To 2 If $aDateSplit[$i] = $iCount Then $sYMD &= '$'& ($i*2 +1) & ($iCount <> 3 ? $sDelim : '') $iCount += 1 ExitLoop EndIf Next Until $iCount = 4 $sStartDate = StringRegExpReplace($sStartDate, '(\d+)(\D)(\d+)(\D)(\d+)', $sYMD) $sStopDate = StringRegExpReplace($sStopDate, '(\d+)(\D)(\d+)(\D)(\d+)', $sYMD) Local $vReverse = False If $sStartDate > $sStopDate Then $vReverse = $sStartDate $sStartDate = $sStopDate $sStopDate = $vReverse EndIf ; internal format = yyyy/mm/dd Local $iStartYear = Number(StringRegExp($sStartDate, '\d+', 3)[0]), $iStopYear = Number(StringRegExp($sStopDate, '\d+', 3)[0]) Local $aTimeLine[(($iStopYear - $iStartYear +1) *366)] $iCount = 0 For $iYear = $iStartYear To $iStopYear For $iMon = 1 To 12 Switch $iMon Case 1, 3, 5, 7, 8, 10, 12 For $iDay = 1 To 31 ; this section of code can be shortened $aTimeLine[$iCount] = $iYear & $sDelim & StringFormat('%02i', $iMon) & $sDelim & StringFormat('%02i', $iDay) If $aTimeLine[$iCount] = $sStopDate Then ExitLoop 3 $iCount += 1 Next Case 4, 6, 9, 11 For $iDay = 1 To 30 $aTimeLine[$iCount] = $iYear & $sDelim & StringFormat('%02i', $iMon) & $sDelim & StringFormat('%02i', $iDay) If $aTimeLine[$iCount] = $sStopDate Then ExitLoop 3 $iCount += 1 Next Case Else For $iDay = 1 To _DateIsLeapYear($iYear) ? 29 : 28 $aTimeLine[$iCount] = $iYear & $sDelim & StringFormat('%02i', $iMon) & $sDelim & StringFormat('%02i', $iDay) If $aTimeLine[$iCount] = $sStopDate Then ExitLoop 3 $iCount += 1 Next EndSwitch Next Next ReDim $aTimeLine[$iCount +1] ; get rid of unused elements For $i = 0 To UBound($aTimeLine) -1 If $aTimeLine[$i] = $sStartDate Then _DeleteRegion($aTimeLine, 1, 0, $i) ExitLoop EndIf Next _Predim($aTimeLine, 2) ; add 2nd dimension ; adding a day name column only works for start dates up to christmas day 2999 [millennium bug], is it worth fixing? ==> [FIXED] If $iDayName <> -1 Then ; $iDayName set to -1 because _DateDayOfWeek() format values range from 0 to 3 ReDim $aTimeLine[UBound($aTimeLine)][2] Local $aNextDay, $iDayNum If $sStartDate <= ('2999' & $sDelim & '12' & $sDelim & '25') Then For $i = 0 To 6 If $i = UBound($aTimeLine) Then ExitLoop $aNextDay = StringRegExp($aTimeLine[$i][0], '\d+', 3) $iDayNum = _DateToDayOfWeek (Number($aNextDay[0]), Number($aNextDay[1]), Number($aNextDay[2])) $aTimeLine[$i][1] = _DateDayOfWeek($iDayNum, $iDayName) Next For $i = 7 To UBound($aTimeLine) -1 $aTimeLine[$i][1] = $aTimeLine[Mod($i, 7)][1] Next Else Local $aDayName[7] For $i = 25 To 31 $aNextDay = StringRegExp('2999/12/' & $i, '\d+', 3) $iDayNum = _DateToDayOfWeek (Number($aNextDay[0]), Number($aNextDay[1]), Number($aNextDay[2])) $aDayName[$i -25] = _DateDayOfWeek($iDayNum, $iDayName) Next Local $iDateDiff = DateRange('2999/12/25', StringReplace($aTimeLine[0][0], $sDelim, '/')) For $i = 0 to 6 If $i = UBound($aTimeLine) Then ExitLoop $aTimeLine[$i][1] = $aDayName[Mod($iDateDiff + $i -1, 7)] Next For $i = 7 To UBound($aTimeLine) -1 $aTimeLine[$i][1] = $aTimeLine[Mod($i, 7)][1] Next EndIf EndIf If $sFormat = Default Then $sFormat = $sYMD ; [regexp pattern stored in ini or settings] For $i = 0 To UBound($aTimeLine) -1 $aTimeLine[$i][0] = StringRegExpReplace($aTimeLine[$i][0], '(\d+)(\D)(\d+)(\D)(\d+)', $sFormat) Next If $vReverse Then _ReverseArray($aTimeLine) _ArrayDisplay($aTimeLine) Return $aTimeLine EndFunc ;==> GetDateArray Edited October 3, 2016 by czardas operator64 ArrayWorkshop
czardas Posted October 3, 2016 Author Posted October 3, 2016 (edited) I just tried US locale settings and I'm also getting the strange results you describe. I should be able to debug it now. If only I had thought of this earlier. Still not there yet though. Edited October 3, 2016 by czardas operator64 ArrayWorkshop
iamtheky Posted October 3, 2016 Posted October 3, 2016 (edited) do yall even UAT (i learned my lesson from the rubiks cube, save and version everything Czardas does) no matter what you select the array looks like this $array[0][0] = 01JAN $BeginDateSelectionYear $array[ubound($array) - 1][1] = 01JAN DAY the day after $EndDateSelectionYear, with Col 0 blank. Edited October 3, 2016 by iamtheky czardas 1 ,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-. |(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/ (_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_) | | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) ( | | | | |)| | \ / | | | | | |)| | `--. | |) \ | | `-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_| '-' '-' (__) (__) (_) (__)
czardas Posted October 3, 2016 Author Posted October 3, 2016 (edited) I think it could be a date formatting discrepancy I haven't accounted for: possibly single digit formatting. I imagine it has to be something quite simple like that. Edited October 3, 2016 by czardas operator64 ArrayWorkshop
iamtheky Posted October 3, 2016 Posted October 3, 2016 if it ends up being that, I would blame it on date.au3 and want to give it an option to normalize data, no? ,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-. |(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/ (_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_) | | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) ( | | | | |)| | \ / | | | | | |)| | `--. | |) \ | | `-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_| '-' '-' (__) (__) (_) (__)
czardas Posted October 3, 2016 Author Posted October 3, 2016 (edited) There do seem to be a few incompatible formats and a degree of inconsistency between working ranges. The function GUICtrlCreateDate() creates day names in any language (and everything else) up to the year 9999. It only gives me the formatted date in my current region when I use GUICtrlRead(), so I have to be able to parse any language format because I don't know the hidden secret - there might not even be one. The function _DateDiff() only works up to the year 3000. I think _DateIsLeapYear() also has inconsistent limitations. [actually not true - I only rewrote it to test it]. I'm sure all these formats/ranges have there individual merit, but it can be tricky to combine them sometimes. Edited October 3, 2016 by czardas operator64 ArrayWorkshop
iamtheky Posted October 3, 2016 Posted October 3, 2016 think normalizing the day and month with stringformat cleared up the spray, where the F is that first day coming from though? expandcollapse popup#include <Array.au3> #include <GUIConstants.au3> #include <GuiEdit.au3> #include <Misc.au3> #include <GuiTab.au3> #include <Date.au3> #include <APILocaleConstants.au3> #include <WinAPILocale.au3> ;#include <ArrayWorkshop.au3> ; required functions are already included in this demo NewTable() Func NewTable(); ($hParent, $idListView, $hListView) ; [missing parent window] Local $sTitle = "New Table", _ $iStyle = BitOR($WS_CAPTION, $WS_POPUP, $WS_SYSMENU), _ $iExStyle = BitOR($WS_EX_MDICHILD, $WS_EX_TOOLWINDOW, $WS_EX_TOPMOST), _ $iWidth = 250, _ $iHeight = 292 Local $hChild = GUICreate($sTitle, $iWidth, $iHeight, Default + 100, Default + 100); , $iStyle, $iExStyle, $hParent) Local $idTab = GUICtrlCreateTab(2, 2, $iWidth -2, $iHeight -32) GUICtrlCreateTabItem("Standard") GUICtrlCreateLabel("Table Dimensions", 14, 35, 120, 20) GUICtrlSetColor(-1, 0x008000) GUICtrlCreateLabel("Number Of Columns", 14, 60, 94, 18) Local $hStandardCols = GUICtrlCreateInput("0", 104 +14, 55, 50, 20, BitOR($WS_TABSTOP, $ES_CENTER, $ES_NUMBER)) GUICtrlSetFont(-1, 10) GUICtrlCreateLabel("Number Of Rows", 14, 83, 90, 18) Local $hStandardRows = GUICtrlCreateInput("0", 104 +14, 81, 50, 20, BitOR($WS_TABSTOP, $ES_CENTER, $ES_NUMBER)) GUICtrlSetFont(-1, 10) GUICtrlCreateLabel("Table Indices", 14, 114, 120, 20) GUICtrlSetColor(-1, 0x008000) Local $hIndices = GUICtrlCreateCheckbox(" Enumerate First Column", 14, 137, 160, 20) ; REMEMBER YES, SETTINGS NO Local $hPadding = GUICtrlCreateCheckbox(" Include Leading Zeros", 14, 161, 124, 20) ; REMEMBER YES, SETTINGS NO GUICtrlCreateTabItem("Advanced") GUICtrlCreateLabel("Column 1 = Date Range", 14, 35, 120, 20) GUICtrlSetColor(-1, 0x008000) GUICtrlCreateLabel("Start Date", 14, 35 +20, 100, 20) Local $idDate1 = GUICtrlCreateDate("", 14, 56 +20, 105, 20, $WS_TABSTOP) GUICtrlCreateLabel("End Date", $iWidth - 118, 35 +20, 100, 20) Local $idDate2 = GUICtrlCreateDate("", $iWidth - 118, 56 +20, 105, 20, BitOR($WS_TABSTOP, $DTS_RIGHTALIGN)) GUICtrlCreateLabel("Column 2 = Days Of The Week (Optional)", 14, 108, 220, 20) GUICtrlSetColor(-1, 0x008000) Local $hCheckBox = GUICtrlCreateCheckbox(" Include Days Of The Week ", 14, 128, 190, 20) ; REMEMBER YES, SETTINGS NO Local $hRadio1 = GUICtrlCreateRadio(" Use Short Name", 14, 151) Local $hRadio2 = GUICtrlCreateRadio(" Use Long Name", $iWidth - 118, 151) GUICtrlSetState(-1, $GUI_CHECKED) GUICtrlSetState($hRadio1, $GUI_DISABLE) ; check settings later GUICtrlSetState($hRadio2, $GUI_DISABLE) ; check settings later GUICtrlCreateLabel("Add More Columns", 14, 181, 222, 20) GUICtrlSetColor(-1, 0x008000) GUICtrlCreateLabel("Total Number Of Columns", 14, 182 +23, 129, 18) Local $hColNum = GUICtrlCreateInput("1", 130 +14, 182 +21, 50, 20, BitOR($WS_TABSTOP, $ES_CENTER, $ES_NUMBER)) ; REMEMBER YES, SETTINGS NO GUICtrlSetFont(-1, 10) GUICtrlCreateTabItem("") ; end tabitem definition Local $hCancel = GUICtrlCreateButton("Cancel", $iWidth -143, $iHeight -25, 66, 20) Local $hOkay = GUICtrlCreateButton("OK", $iWidth -69, $iHeight -25, 66, 20) GUISetState(@SW_SHOW) Local $msg2, $bDisable = True, $iMaxFields = 65000, $bStandardError = False, $iRows = 0, $iCols = 0, _ $sMonitorAdv = GUICtrlRead($idDate1) & GUICtrlRead($idDate2) & GUICtrlRead($hColNum), $sDate1, $sDate2, $sColsAdv, $iDiff, $bErrorAdv = False While 1 $msg2 = GUIGetMsg() If $msg2 = $hCancel Or $msg2 = $GUI_EVENT_CLOSE Then ExitLoop If BitAND(GUICtrlRead($hCheckBox), $GUI_CHECKED) == $GUI_CHECKED Then If $bDisable Then GUICtrlSetState($hRadio1, $GUI_ENABLE) GUICtrlSetState($hRadio2, $GUI_ENABLE) $bDisable = False EndIf ElseIf Not $bDisable Then GUICtrlSetState($hRadio1, $GUI_DISABLE) GUICtrlSetState($hRadio2, $GUI_DISABLE) $bDisable = True EndIf $sDate1 = GUICtrlRead($idDate1) $sDate2 = GUICtrlRead($idDate2) $sColsAdv = GUICtrlRead($hColNum) If $sDate1 & $sDate2 & $sColsAdv <> $sMonitorAdv Then $iDiff = DateRange(LocaleDateToYMD($sDate1), LocaleDateToYMD($sDate2)) ; _DateDiff() is too limited If $iDiff * $sColsAdv > $iMaxFields Then If Not $bErrorAdv Then GUICtrlSetBkColor($hColNum, 0xFFA090) $bErrorAdv = True EndIf ElseIf $bErrorAdv Then GUICtrlSetBkColor($hColNum, 0xFFFFFF) $bErrorAdv = False EndIf $sMonitorAdv = $sDate1 & $sDate2 & $sColsAdv EndIf $iCols = GUICtrlRead($hStandardCols) $iRows = GUICtrlRead($hStandardRows) If Not $iRows Then GUICtrlSetData($hStandardRows, 0) If Not $iCols Then GUICtrlSetData($hStandardCols, 0) If ControlGetFocus($hChild) <> "Edit2" And StringRegExp($iRows, '\A0+[1-9]') Then GUICtrlSetData($hStandardRows, StringRegExpReplace($iRows, '(\A0+)([1-9])(\d+)*', '$2$3')) If ControlGetFocus($hChild) <> "Edit1" And StringRegExp($iCols, '\A0+[1-9]') Then GUICtrlSetData($hStandardCols, StringRegExpReplace($iCols, '(\A0+)([1-9])(\d+)*', '$2$3')) If $iRows > $iMaxFields Or $iCols > $iMaxFields Or GUICtrlRead($hStandardRows) * GUICtrlRead($hStandardCols) > $iMaxFields Then If Not $bStandardError Then GUICtrlSetBkColor($hStandardRows, 0xFFA090) GUICtrlSetBkColor($hStandardCols, 0xFFA090) $bStandardError = True EndIf ElseIf $bStandardError Then GUICtrlSetBkColor($hStandardRows, 0xFFFFFF) GUICtrlSetBkColor($hStandardCols, 0xFFFFFF) $bStandardError = False EndIf $iCols = GUICtrlRead($hColNum) If ControlGetFocus($hChild) <> "Edit3" And StringRegExp($iCols, '\A0+[1-9]') Then GUICtrlSetData($hColNum, StringRegExpReplace($iCols, '(\A0+)([1-9])(\d+)*', '$2$3')) $iCols = GUICtrlRead($hColNum) If $iCols < 1 Then If BitAND(GUICtrlRead($hCheckBox), $GUI_CHECKED) == $GUI_CHECKED And ControlGetFocus($hChild) <> "Edit3" Then GUICtrlSetData($hColNum, 2) Else GUICtrlSetData($hColNum, 1) EndIf If ControlGetFocus($hChild) = "Edit3" Then _GUICtrlEdit_SetSel($hColNum, 0, -1) EndIf If BitAND(GUICtrlRead($hCheckBox), $GUI_CHECKED) == $GUI_CHECKED Then If $iCols < 2 And ControlGetFocus($hChild) <> "Edit3" Then If ControlGetFocus($hChild) = "Button3" Then While _IsPressed('01') Sleep(20) WEnd EndIf If BitAND(GUICtrlRead($hCheckBox), $GUI_CHECKED) == $GUI_CHECKED Then GUICtrlSetData($hColNum, 2) Else GUICtrlSetData($hColNum, 1) EndIf EndIf Else If $iCols < 1 Then GUICtrlSetData($hColNum, 1) If ControlGetFocus($hChild) = "Edit3" Then _GUICtrlEdit_SetSel($hColNum, 0, -1) EndIf EndIf If $msg2 = $hOkay Then If $bErrorAdv Then MsgBox(262160, "uh-uh!", "Out of Range") ContinueLoop EndIf Local $sDelim = '-' ; read from settings ??? [maybe] If _GUICtrlTab_GetCurFocus($idTab) = 1 Then Local $iName, $sFormat = Default ; read from settings [ini] If BitAND(GUICtrlRead($hCheckBox), $GUI_CHECKED) == $GUI_CHECKED Then $iName = (BitAND(GUICtrlRead($hRadio1), $GUI_CHECKED) == $GUI_CHECKED) ? 3 : 2 Else $iName = -1 EndIf ; $sStartDate, $sStopDate, $sDelim = Default, $sFormat = Default, $iDayName = -1) GetDateArray(GUICtrlRead($idDate1), GUICtrlRead($idDate2), $sDelim, $sFormat, $iName) ; US [, '$3-$5-$1']) EndIf EndIf WEnd GUIDelete($hChild) EndFunc ;==> NewTable Func LocaleDateToYMD($sDate, $sDelim = '/') Local $iID = _WinAPI_GetUserDefaultLCID(), _ $aDateSplit = StringRegExp(_WinAPI_GetLocaleInfo($iID, $LOCALE_SSHORTDATE), '\w+', 3), _ $vTest = True ; [floating variable] If IsArray($aDateSplit) And UBound($aDateSplit) = 3 Then For $i = 0 To 2 ; determine the locale ymd order If StringInStr($aDateSplit[$i], 'y') Then $aDateSplit[$i] = 1 ; year ElseIf StringInStr($aDateSplit[$i], 'm') Then $aDateSplit[$i] = 2 ; month ElseIf StringInStr($aDateSplit[$i], 'd') Then $aDateSplit[$i] = 3 ; day EndIf Next $vTest = $aDateSplit[0] & $aDateSplit[1] & $aDateSplit[2] If StringInStr($vTest, '1') And StringInStr($vTest, '2') And StringInStr($vTest, '3') Then $vTest = False ; success EndIf If $vTest Then ; failure with the previous method [both methods work on Win7 in the UK] Local $sLongDate = _WinAPI_GetDateFormat(0, 0, $DATE_LONGDATE) $aDateSplit = StringRegExp($sLongDate, '(*UCP)\w+', 3) If Not IsArray($aDateSplit) And UBound($aDateSplit) <> 3 Then Return SetError(1) ; undetermined error? For $i = 0 To 2 ; determine the locale ymd order If $aDateSplit[$i] = @YEAR Then ; hopefully this method will work for all international regions $aDateSplit[$i] = 1 ; year ElseIf $aDateSplit[$i] = _DateToMonth(@MON, $DMW_LOCALE_LONGNAME) Then $aDateSplit[$i] = 2 ; month Else $aDateSplit[$i] = 3 ; day EndIf Next $vTest = $aDateSplit[0] & $aDateSplit[1] & $aDateSplit[2] If Not (StringInStr($vTest, '1') And StringInStr($vTest, '2') And StringInStr($vTest, '3')) Then Return SetError(2) ; undetermined error? EndIf Local $iCount = 1, $sYMD = '' Do For $i = 0 To 2 If $aDateSplit[$i] = $iCount Then $sYMD &= '$'& ($i*2 +1) & ($iCount <> 3 ? $sDelim : '') $iCount += 1 ExitLoop EndIf Next Until $iCount = 4 Return StringRegExpReplace($sDate, '(\d+)(\D)(\d+)(\D)(\d+)', $sYMD) EndFunc Func GetDateArray($sStartDate, $sStopDate, $sDelim = Default, $sFormat = Default, $iDayName = -1) Local $iID = _WinAPI_GetUserDefaultLCID(), _ $aDateSplit = StringRegExp(_WinAPI_GetLocaleInfo($iID, $LOCALE_SSHORTDATE), '\w+', 3) If IsArray($aDateSplit) And UBound($aDateSplit) = 3 Then For $i = 0 To 2 ; determine the locale ymd order If StringInStr($aDateSplit[$i], 'y') Then $aDateSplit[$i] = 1 ; year ElseIf StringInStr($aDateSplit[$i], 'm') Then $aDateSplit[$i] = 2 ; month ElseIf StringInStr($aDateSplit[$i], 'd') Then $aDateSplit[$i] = 3 ; day EndIf Next Else ; let's try an alternative method [both methods work on Win7 in the UK] Local $sLongDate = _WinAPI_GetDateFormat(0, 0, $DATE_LONGDATE) $aDateSplit = StringRegExp($sLongDate, '(*UCP)\w+', 3) If Not IsArray($aDateSplit) And UBound($aDateSplit) <> 3 Then Return SetError(1) ; undetermined error? For $i = 0 To 2 ; determine the locale ymd order If $aDateSplit[$i] = @YEAR Then ; hopefully this method will work for all international regions $aDateSplit[$i] = 1 ; year ElseIf $aDateSplit[$i] = _DateToMonth(@MON, $DMW_LOCALE_LONGNAME) Then $aDateSplit[$i] = 2 ; month Else $aDateSplit[$i] = 3 ; day EndIf Next EndIf ; check the array contains numbers 1 to 3 Local $sTest = $aDateSplit[0] & $aDateSplit[1] & $aDateSplit[2] If Not (StringInStr($sTest, '1') And StringInStr($sTest, '2') And StringInStr($sTest, '3')) Then Return SetError(2) ; undetermined error? If $sDelim = Default Then $sDelim = StringRegExp($sStartDate, '\D+', 3)[0] Local $iCount = 1, $sYMD = '' Do For $i = 0 To 2 If $aDateSplit[$i] = $iCount Then $sYMD &= '$'& ($i*2 +1) & ($iCount <> 3 ? $sDelim : '') $iCount += 1 ExitLoop EndIf Next Until $iCount = 4 $sStartDate = StringRegExpReplace($sStartDate, '(\d+)(\D)(\d+)(\D)(\d+)', $sYMD) $sStopDate = StringRegExpReplace($sStopDate, '(\d+)(\D)(\d+)(\D)(\d+)', $sYMD) Local $vReverse = False If $sStartDate > $sStopDate Then $vReverse = $sStartDate $sStartDate = $sStopDate $sStopDate = $vReverse EndIf ; internal format = yyyy/mm/dd Local $iStartYear = Number(StringRegExp($sStartDate, '\d+', 3)[0]), $iStopYear = Number(StringRegExp($sStopDate, '\d+', 3)[0]) Local $aTimeLine[(($iStopYear - $iStartYear +1) *366)] $iCount = 0 For $iYear = $iStartYear To $iStopYear For $iMon = 1 To 12 Switch $iMon Case 1, 3, 5, 7, 8, 10, 12 For $iDay = 1 To 31 ; this section of code can be shortened $aTimeLine[$iCount] = $iYear & $sDelim & StringFormat('%02i', $iMon) & $sDelim & StringFormat('%02i', $iDay) If $aTimeLine[$iCount] = $sStopDate Then ExitLoop 3 $iCount += 1 Next Case 4, 6, 9, 11 For $iDay = 1 To 30 $aTimeLine[$iCount] = $iYear & $sDelim & StringFormat('%02i', $iMon) & $sDelim & StringFormat('%02i', $iDay) If $aTimeLine[$iCount] = $sStopDate Then ExitLoop 3 $iCount += 1 Next Case Else For $iDay = 1 To IsLeapYear($iYear) ? 29 : 28 $aTimeLine[$iCount] = $iYear & $sDelim & StringFormat('%02i', $iMon) & $sDelim & StringFormat('%02i', $iDay) If $aTimeLine[$iCount] = $sStopDate Then ExitLoop 3 $iCount += 1 Next EndSwitch Next Next ReDim $aTimeLine[$iCount +1] ; get rid of unused elements For $i = 0 To UBound($aTimeLine) -1 If $aTimeLine[$i] = $sStartDate Then _DeleteRegion($aTimeLine, 1, 0, $i) ExitLoop EndIf Next _Predim($aTimeLine, 2) ; add 2nd dimension ; adding a day name column only works for start dates up to christmas day 2999 [millennium bug], is it worth fixing? ==> [FIXED] If $iDayName <> -1 Then ; $iDayName set to -1 because _DateDayOfWeek() format values range from 0 to 3 ReDim $aTimeLine[UBound($aTimeLine)][2] Local $aNextDay, $iDayNum If $sStartDate <= ('2999' & $sDelim & '12' & $sDelim & '25') Then For $i = 0 To 6 If $i = UBound($aTimeLine) Then ExitLoop $aNextDay = StringRegExp($aTimeLine[$i][0], '\d+', 3) $iDayNum = _DateToDayOfWeek (Number($aNextDay[0]), Number($aNextDay[1]), Number($aNextDay[2])) $aTimeLine[$i][1] = _DateDayOfWeek($iDayNum, $iDayName) Next For $i = 7 To UBound($aTimeLine) -1 $aTimeLine[$i][1] = $aTimeLine[Mod($i, 7)][1] Next Else Local $aDayName[7] For $i = 25 To 31 $aNextDay = StringRegExp('2999/12/' & $i, '\d+', 3) $iDayNum = _DateToDayOfWeek (Number($aNextDay[0]), Number($aNextDay[1]), Number($aNextDay[2])) $aDayName[$i -25] = _DateDayOfWeek($iDayNum, $iDayName) Next Local $iDateDiff = DateRange('2999/12/25', StringReplace($aTimeLine[0][0], $sDelim, '/')) For $i = 0 to 6 If $i = UBound($aTimeLine) Then ExitLoop $aTimeLine[$i][1] = $aDayName[Mod($iDateDiff + $i -1, 7)] Next For $i = 7 To UBound($aTimeLine) -1 $aTimeLine[$i][1] = $aTimeLine[Mod($i, 7)][1] Next EndIf EndIf If $sFormat = Default Then ; [regexp pattern stored in ini or settings] $aDateSplit = StringRegExp($sYMD, '\d', 3) _Predim($aDateSplit, 2) ReDim $aDateSplit[3][2] $aDateSplit[0][1] = 1 $aDateSplit[1][1] = 3 $aDateSplit[2][1] = 5 _ArraySort($aDateSplit) $sFormat = '$' & $aDateSplit[0][1] & $sDelim & '$' & $aDateSplit[1][1] & $sDelim & '$' & $aDateSplit[2][1] EndIf For $i = 0 To UBound($aTimeLine) -1 $aTimeLine[$i][0] = StringRegExpReplace($aTimeLine[$i][0], '(\d+)(\D)(\d+)(\D)(\d+)', $sFormat) Next If $vReverse Then _ReverseArray($aTimeLine) _ArrayDisplay($aTimeLine) Return $aTimeLine EndFunc ;==> GetDateArray Func IsLeapYear($iYear) If Mod($iYear, 4) Then Return False ElseIf Mod($iYear, 100) Then Return True ElseIf Mod($iYear, 400) Then Return False Else Return True EndIf EndFunc ;==> IsLeapYear Func DateRange($sDate1, $sDate2) ; must be yyyy/mm/dd $aDate1 = stringsplit($sDate1 , "/") $aDate1[2] = stringformat("%02i" , $aDate1[2]) $aDate1[3] = stringformat("%02i" , $aDate1[3]) $aDate2 = stringsplit($sDate1 , "/") $aDate2[2] = stringformat("%02i" , $aDate2[2]) $aDate2[3] = stringformat("%02i" , $aDate2[3]) ;~ msgbox(0, '' , $aDate1[1] & @LF & $aDate1[2] & @LF & $aDate1[3]) $sDate1 = $aDate1[1] & "/" & $aDate1[2] & "/" & $aDate1[3] $sDate2 = $aDate2[1] & "/" & $aDate2[2] & "/" & $aDate2[3] ;~ msgbox(0, '' , $sDate1 & @LF & $sDate2) Local $vTemp If $sDate1 > $sDate2 Then $vTemp = $sDate1 $sDate1 = $sDate2 $sDate2 = $vTemp EndIf Local $aArray1 = StringRegExp($sDate1, '\d+', 3), $aArray2 = StringRegExp($sDate2, '\d+', 3) For $i = 0 To 2 $aArray1[$i] = Number($aArray1[$i]) $aArray2[$i] = Number($aArray2[$i]) Next Local $iCount = 0 For $i = $aArray1[0] +1 To $aArray2[0] -1 If Not IsLeapYear($i) Then $iCount += 365 Else $iCount += 366 EndIf Next Local $iFirstMonth = 0 Switch $aArray1[1] Case 1, 3, 5, 7, 8, 10, 12 $iFirstMonth = 32 - $aArray1[2] Case 4, 6, 9, 11 $iFirstMonth = 31 - $aArray1[2] Case Else $iFirstMonth = (IsLeapYear($aArray1[0]) ? 30 : 29) - $aArray1[2] EndSwitch If $aArray1[0] < $aArray2[0] Then $iCount += $iFirstMonth For $i = $aArray1[1] +1 to 12 Switch $i Case 1, 3, 5, 7, 8, 10, 12 $iCount += 31 Case 4, 6, 9, 11 $iCount += 30 Case Else $iCount += (IsLeapYear($aArray1[0]) ? 29 : 28) EndSwitch Next $iCount += $aArray2[2] ; add remaining days in final month If $aArray2[1] > 1 Then For $i = 1 To $aArray2[1] -1 Switch $i Case 1, 3, 5, 7, 8, 10, 12 $iCount += 31 Case 4, 6, 9, 11 $iCount += 30 Case Else $iCount += (IsLeapYear($aArray2[0]) ? 29 : 28) EndSwitch Next EndIf ElseIf $aArray1[1] < $aArray2[1] Then ; same year, different month $iCount += $iFirstMonth For $i = $aArray1[1] +1 to $aArray2[1] -1 Switch $i Case 1, 3, 5, 7, 8, 10, 12 $iCount += 31 Case 4, 6, 9, 11 $iCount += 30 Case Else $iCount += (IsLeapYear($aArray1[0]) ? 29 : 28) EndSwitch Next $iCount += $aArray2[2] Else ; same month and year $iCount = $aArray2[2] - $aArray1[2] +1 EndIf Return $iCount EndFunc ;==> DateRange ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Functions from ArrayWorkshop.au3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #Au3Stripper_Off Func _ReverseArray(ByRef $aArray, $iDimension = 1, $iStart = 0, $iEnd = -1) If Not IsArray($aArray) Or UBound($aArray, 0) > 9 Then Return SetError(1) ; not a valid array Local $aBound = __GetBounds($aArray) If @error Then Return SetError(2) ; array contains zero elements $iDimension = ($iDimension = Default) ? 1 : Int($iDimension) If $iDimension < 1 Or $iDimension > $aBound[0] Then Return SetError(3) ; dimension does not exist $iStart = ($iStart = Default) ? 0 : Int($iStart) If $iStart < 0 Or $iStart > $aBound[$iDimension] - 2 Then Return SetError(4) ; meaningless $iStart value $iEnd = ($iEnd = -1 Or $iEnd = Default) ? $aBound[$iDimension] - 1 : Int($iEnd) If $iEnd <= $iStart Or $iEnd >= $aBound[$iDimension] Then Return SetError(5) ; meaningless $iEnd value If $aBound[0] = 1 Then ___Reverse1D($aArray, $iStart, $iEnd) Else $aBound[$iDimension] = 1 Local $aRegion = ___NewArray($aBound) ; to store extracted regions For $i = 1 To $aBound[0] $aBound[$i] -= 1 Next Local $sIndices = __HiddenIndices($aBound[0], $iDimension), $fnFloodFill = __FloodFunc()[$aBound[0]], _ $sTransfer = '$aSource' & $sIndices ; array syntax While $iEnd > $iStart $fnFloodFill($aRegion, $aBound, $iDimension, 0, $iStart, $aArray, $sTransfer) ; extract the current start region $sTransfer = '$aTarget' & $sIndices $fnFloodFill($aArray, $aBound, $iDimension, $iStart, $iEnd, '', $sTransfer) ; overwrite the current start region $sTransfer = '$aSource' & $sIndices $fnFloodFill($aArray, $aBound, $iDimension, $iEnd, 0, $aRegion, $sTransfer) ; overwrite the current end region $iStart += 1 $iEnd -= 1 WEnd EndIf EndFunc ;==>_ReverseArray Func _DeleteRegion(ByRef $aArray, $iDimension = 1, $iSubIndex = 0, $iRange = 1) If Not IsArray($aArray) Then Return SetError(1) Local $aBound = __GetBounds($aArray) ; get the bounds of each dimension If @error Then Return SetError(4) ; $aArray must contain at least one element If $aBound[0] > 9 Then Return SetError(2) ; nine dimension limit $iDimension = ($iDimension = Default) ? 1 : Int($iDimension) If $iDimension > $aBound[0] Or $iDimension < 1 Then Return SetError(3) ; out of bounds dimension $iSubIndex = ($iSubIndex = Default) ? 0 : Int($iSubIndex) If $iSubIndex < 0 Or $iSubIndex > $aBound[$iDimension] - 1 Then Return SetError(5) ; sub-index does not exist in the dimension $iRange = ($iRange = Default) ? 1 : Int($iRange) If $iRange < 1 Then Return SetError(6) ; range must be greater than zero $iRange = ($iSubIndex + $iRange < $aBound[$iDimension]) ? $iRange : $aBound[$iDimension] - $iSubIndex ; corrects for overflow If $iRange = $aBound[$iDimension] Then Return SetError(6) ; deleting the whole region is not currently supported [give reason] $aBound[$iDimension] -= $iRange ; the size of the dimension in the new array If $aBound[0] = 1 Then For $iNext = $iSubIndex To $aBound[$iDimension] - 1 $aArray[$iNext] = $aArray[$iNext + $iRange] Next ReDim $aArray[$aBound[$iDimension]] Return EndIf Local $iMaxIndex = $aBound[$iDimension] - 1 For $i = 1 To $aBound[0] $aBound[$i] -= 1 Next $aBound[$iDimension] = 0 ; set to loop once [one region at a time] Local $iFrom, $sTransfer = '$aTarget' & __HiddenIndices($aBound[0], $iDimension), $fnFloodFill = __FloodFunc()[$aBound[0]] For $iNext = $iSubIndex To $iMaxIndex $iFrom = $iNext + $iRange $fnFloodFill($aArray, $aBound, $iDimension, $iNext, $iFrom, '', $sTransfer) ; overwrite the final [untouched] region Next $aBound[$iDimension] = $iMaxIndex For $i = 1 To $aBound[0] $aBound[$i] += 1 Next __ResetBounds($aArray, $aBound) ; delete remaining indices EndFunc ;==>_DeleteRegion Func _PreDim(ByRef $aArray, $iDimensions, $bPush = False) If Not IsArray($aArray) Then Return SetError(1) $iDimensions = Int($iDimensions) If $iDimensions < 1 Or $iDimensions > 9 Then Return SetError(2) Local $iPreDims = UBound($aArray, 0) ; current number of dimensions If $iPreDims = $iDimensions Then Return ; no change If $iPreDims > 9 Then Return SetError(3) ; too many dimensions Local $aBound = __GetBounds($aArray) ; get the size of each original dimension If @error Then Return SetError(4) ; $aArray must contain at least one element $aBound[0] = $iDimensions ; overwrite this value with the new number of dimensions Local $sTransfer = '[$a[1]][$a[2]][$a[3]][$a[4]][$a[5]][$a[6]][$a[7]][$a[8]][$a[9]]' ; array syntax to be sent to the remote loop region If $bPush Then ; prefix dimensions, or delete from the left Local $iOffset = Abs($iDimensions - $iPreDims) If $iPreDims > $iDimensions Then ; lower dimensions get deleted For $i = 1 To $iDimensions ; shift elements to lower indices $aBound[$i] = $aBound[$i + $iOffset] Next $sTransfer = '$aSource' & StringLeft('[0][0][0][0][0][0][0][0]', $iOffset * 3) & StringLeft($sTransfer, $iDimensions * 7) Else ; lower dimensions are created ReDim $aBound[$iDimensions + 1] ; make space for more dimensions For $i = $iDimensions To $iOffset + 1 Step -1 ; shift elements to higher indices $aBound[$i] = $aBound[$i - $iOffset] Next For $i = 1 To $iOffset ; assign the size of each additional dimension [1][1][1]... etc... $aBound[$i] = 1 Next $sTransfer = '$aSource' & StringMid($sTransfer, 1 + $iOffset * 7, $iPreDims * 7) EndIf Else ; Default behaviour = append dimensions, or delete from the right ReDim $aBound[$iDimensions + 1] ; modify the number of dimensions [according to the new array] For $i = $iPreDims + 1 To $iDimensions ; assign the size of each new dimension ...[1][1][1] etc... $aBound[$i] = 1 Next $sTransfer = '$aSource' & StringLeft($sTransfer, $iPreDims * 7) EndIf ; add or remove dimensions Local $aNewArray = ___NewArray($aBound) For $i = 1 To $iDimensions $aBound[$i] -= 1 ; convert elements to the maximum index value within each dimension Next ; access the remote loop region Local $iSubIndex = 0, $aFloodFill = __FloodFunc() $aFloodFill[$iDimensions]($aNewArray, $aBound, 0, $iSubIndex, '', $aArray, $sTransfer) $aArray = $aNewArray EndFunc ;==>_PreDim Func __GetBounds($aArray, $iHypothetical = 0) Local $iMaxDim = UBound($aArray, 0) Local $aBound[($iHypothetical ? $iHypothetical : $iMaxDim) + 1] ; [or ==> Local $aBound[9]] $aBound[0] = $iMaxDim For $i = 1 To $iMaxDim $aBound[$i] = UBound($aArray, $i) If $aBound[$i] = 0 Then Return SetError(1) Next If $iHypothetical Then For $i = $iMaxDim + 1 To $iHypothetical $aBound[$i] = 1 ; imaginary dimensions Next EndIf Return $aBound EndFunc ;==>__GetBounds Func __HiddenIndices($iBound, $iDimension) Local $sSyntax = '' ; to access elements at their original indices For $i = 1 To $iBound If $i <> $iDimension Then $sSyntax &= '[$a[' & $i & ']]' ; default ==> '$aSource[$iFrom][$a[2]][$a[3]][$a[4]][$a[5]] etc...' Else $sSyntax &= '[$iFrom]' EndIf Next Return $sSyntax EndFunc ;==>__HiddenIndices Func ___NewArray($aBound) Switch $aBound[0] Case 1 Local $aArray[$aBound[1]] Case 2 Local $aArray[$aBound[1]][$aBound[2]] Case 3 Local $aArray[$aBound[1]][$aBound[2]][$aBound[3]] Case 4 Local $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]] Case 5 Local $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]] Case 6 Local $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]][$aBound[6]] Case 7 Local $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]][$aBound[6]][$aBound[7]] Case 8 Local $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]][$aBound[6]][$aBound[7]][$aBound[8]] Case 9 Local $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]][$aBound[6]][$aBound[7]][$aBound[8]][$aBound[9]] EndSwitch Return $aArray EndFunc ;==>___NewArray Func ___Reverse1D(ByRef $aArray, $iStart, $iStop) Local $vTemp While $iStop > $iStart $vTemp = $aArray[$iStart] $aArray[$iStart] = $aArray[$iStop] $aArray[$iStop] = $vTemp $iStart += 1 $iStop -= 1 WEnd EndFunc ;==>___Reverse1D Func __ResetBounds(ByRef $aArray, $aBound) Switch $aBound[0] Case 1 ReDim $aArray[$aBound[1]] Case 2 ReDim $aArray[$aBound[1]][$aBound[2]] Case 3 ReDim $aArray[$aBound[1]][$aBound[2]][$aBound[3]] Case 4 ReDim $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]] Case 5 ReDim $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]] Case 6 ReDim $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]][$aBound[6]] Case 7 ReDim $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]][$aBound[6]][$aBound[7]] Case 8 ReDim $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]][$aBound[6]][$aBound[7]][$aBound[8]] Case 9 ReDim $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]][$aBound[6]][$aBound[7]][$aBound[8]][$aBound[9]] EndSwitch EndFunc ;==>__ResetBounds Func __FloodFunc() ; [modified for this demo] Local $aFloodFunc = ['', ___Flood1D, ___Flood2D] ; , ___Flood3D, ___Flood4D, ___Flood5D, ___Flood6D, ___Flood7D, ___Flood8D, ___Flood9D] Return $aFloodFunc EndFunc ;==>__FloodFunc Func ___Flood1D(ByRef $aTarget, $aBound, $iDimension, $iSubIndex, $iFrom, $aSource, $sTransfer) ; [still experimental] #forceref $iDimension, $iFrom, $aSource ; $iDimension would normally not apply here (special case) Local $a[10] = ['', 0, 0, 0, 0, 0, 0, 0, 0, 0] ; loop iteration count [or indices of higher dimensions within the source array] For $a[1] = $iSubIndex To $aBound[1] ; from the start to the bounds of the 1st dimension (special case) ; only one operation is needed in this special case $aTarget[$a[1]] = Execute($sTransfer) ; hidden parameters may appear in the code being executed Next EndFunc ;==>___Flood1D Func ___Flood2D(ByRef $aTarget, $aBound, $iDimension, $iSubIndex, $iFrom, $aSource, $sTransfer) #forceref $iFrom, $aSource ; hidden parameters Local $a[10] = ['', 0, 0, 0, 0, 0, 0, 0, 0, 0] ; loop iteration count [or indices of higher dimensions within the source array] For $a[2] = 0 To $aBound[2] For $a[1] = 0 To $aBound[1] $a[$iDimension] = $iSubIndex ; override the iteration count (fast method) - $a[0] has no influence $aTarget[$a[1]][$a[2]] = Execute($sTransfer) ; hidden parameters may appear in the code being executed Next Next EndFunc ;==>___Flood2D #Au3Stripper_On ,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-. |(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/ (_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_) | | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) ( | | | | |)| | \ / | | | | | |)| | `--. | |) \ | | `-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_| '-' '-' (__) (__) (_) (__)
czardas Posted October 3, 2016 Author Posted October 3, 2016 (edited) It's a bug in the recognition of Start/End Date. I'm now almost certain that it's a format recognition issue, and that some kind of universal date format recognition algorithm should fix it. Grab some dates, analyse the locale format and then tweak the recognition pattern (if I'm right). I'm not brave enough to set my locale to Chinese, in case I can't undo the changes. Edited October 3, 2016 by czardas operator64 ArrayWorkshop
czardas Posted October 3, 2016 Author Posted October 3, 2016 (edited) @iamtheky You were heading the right direction, but on a parallel path. How's this? The empty elements have gone away. expandcollapse popup#include <Array.au3> #include <GUIConstants.au3> #include <GuiEdit.au3> #include <Misc.au3> #include <GuiTab.au3> #include <Date.au3> #include <APILocaleConstants.au3> #include <WinAPILocale.au3> ;#include <ArrayWorkshop.au3> ; required functions are already included in this demo NewTable() Func NewTable(); ($hParent, $idListView, $hListView) ; [missing parent window] Local $sTitle = "New Table", _ $iStyle = BitOR($WS_CAPTION, $WS_POPUP, $WS_SYSMENU), _ $iExStyle = BitOR($WS_EX_MDICHILD, $WS_EX_TOOLWINDOW, $WS_EX_TOPMOST), _ $iWidth = 250, _ $iHeight = 292 Local $hChild = GUICreate($sTitle, $iWidth, $iHeight, Default + 100, Default + 100); , $iStyle, $iExStyle, $hParent) Local $idTab = GUICtrlCreateTab(2, 2, $iWidth -2, $iHeight -32) GUICtrlCreateTabItem("Standard") GUICtrlCreateLabel("Table Dimensions", 14, 35, 120, 20) GUICtrlSetColor(-1, 0x008000) GUICtrlCreateLabel("Number Of Columns", 14, 60, 94, 18) Local $hStandardCols = GUICtrlCreateInput("0", 104 +14, 55, 50, 20, BitOR($WS_TABSTOP, $ES_CENTER, $ES_NUMBER)) GUICtrlSetFont(-1, 10) GUICtrlCreateLabel("Number Of Rows", 14, 83, 90, 18) Local $hStandardRows = GUICtrlCreateInput("0", 104 +14, 81, 50, 20, BitOR($WS_TABSTOP, $ES_CENTER, $ES_NUMBER)) GUICtrlSetFont(-1, 10) GUICtrlCreateLabel("Table Indices", 14, 114, 120, 20) GUICtrlSetColor(-1, 0x008000) Local $hIndices = GUICtrlCreateCheckbox(" Enumerate First Column", 14, 137, 160, 20) ; REMEMBER YES, SETTINGS NO Local $hPadding = GUICtrlCreateCheckbox(" Include Leading Zeros", 14, 161, 124, 20) ; REMEMBER YES, SETTINGS NO GUICtrlCreateTabItem("Advanced") GUICtrlCreateLabel("Column 1 = Date Range", 14, 35, 120, 20) GUICtrlSetColor(-1, 0x008000) GUICtrlCreateLabel("Start Date", 14, 35 +20, 100, 20) Local $idDate1 = GUICtrlCreateDate("", 14, 56 +20, 105, 20, $WS_TABSTOP) GUICtrlCreateLabel("End Date", $iWidth - 118, 35 +20, 100, 20) Local $idDate2 = GUICtrlCreateDate("", $iWidth - 118, 56 +20, 105, 20, BitOR($WS_TABSTOP, $DTS_RIGHTALIGN)) GUICtrlCreateLabel("Column 2 = Days Of The Week (Optional)", 14, 108, 220, 20) GUICtrlSetColor(-1, 0x008000) Local $hCheckBox = GUICtrlCreateCheckbox(" Include Days Of The Week ", 14, 128, 190, 20) ; REMEMBER YES, SETTINGS NO Local $hRadio1 = GUICtrlCreateRadio(" Use Short Name", 14, 151) Local $hRadio2 = GUICtrlCreateRadio(" Use Long Name", $iWidth - 118, 151) GUICtrlSetState(-1, $GUI_CHECKED) GUICtrlSetState($hRadio1, $GUI_DISABLE) ; check settings later GUICtrlSetState($hRadio2, $GUI_DISABLE) ; check settings later GUICtrlCreateLabel("Add More Columns", 14, 181, 222, 20) GUICtrlSetColor(-1, 0x008000) GUICtrlCreateLabel("Total Number Of Columns", 14, 182 +23, 129, 18) Local $hColNum = GUICtrlCreateInput("1", 130 +14, 182 +21, 50, 20, BitOR($WS_TABSTOP, $ES_CENTER, $ES_NUMBER)) ; REMEMBER YES, SETTINGS NO GUICtrlSetFont(-1, 10) GUICtrlCreateTabItem("") ; end tabitem definition Local $hCancel = GUICtrlCreateButton("Cancel", $iWidth -143, $iHeight -25, 66, 20) Local $hOkay = GUICtrlCreateButton("OK", $iWidth -69, $iHeight -25, 66, 20) GUISetState(@SW_SHOW) Local $msg2, $bDisable = True, $iMaxFields = 65000, $bStandardError = False, $iRows = 0, $iCols = 0, _ $sMonitorAdv = GUICtrlRead($idDate1) & GUICtrlRead($idDate2) & GUICtrlRead($hColNum), $sDate1, $sDate2, $sColsAdv, $iDiff, $bErrorAdv = False While 1 $msg2 = GUIGetMsg() If $msg2 = $hCancel Or $msg2 = $GUI_EVENT_CLOSE Then ExitLoop If BitAND(GUICtrlRead($hCheckBox), $GUI_CHECKED) == $GUI_CHECKED Then If $bDisable Then GUICtrlSetState($hRadio1, $GUI_ENABLE) GUICtrlSetState($hRadio2, $GUI_ENABLE) $bDisable = False EndIf ElseIf Not $bDisable Then GUICtrlSetState($hRadio1, $GUI_DISABLE) GUICtrlSetState($hRadio2, $GUI_DISABLE) $bDisable = True EndIf $sDate1 = GUICtrlRead($idDate1) $sDate2 = GUICtrlRead($idDate2) $sColsAdv = GUICtrlRead($hColNum) If $sDate1 & $sDate2 & $sColsAdv <> $sMonitorAdv Then $iDiff = DateRange(LocaleDateToYMD($sDate1), LocaleDateToYMD($sDate2)) ; _DateDiff() is too limited If $iDiff * $sColsAdv > $iMaxFields Then If Not $bErrorAdv Then GUICtrlSetBkColor($hColNum, 0xFFA090) $bErrorAdv = True EndIf ElseIf $bErrorAdv Then GUICtrlSetBkColor($hColNum, 0xFFFFFF) $bErrorAdv = False EndIf $sMonitorAdv = $sDate1 & $sDate2 & $sColsAdv EndIf $iCols = GUICtrlRead($hStandardCols) $iRows = GUICtrlRead($hStandardRows) If Not $iRows Then GUICtrlSetData($hStandardRows, 0) If Not $iCols Then GUICtrlSetData($hStandardCols, 0) If ControlGetFocus($hChild) <> "Edit2" And StringRegExp($iRows, '\A0+[1-9]') Then GUICtrlSetData($hStandardRows, StringRegExpReplace($iRows, '(\A0+)([1-9])(\d+)*', '$2$3')) If ControlGetFocus($hChild) <> "Edit1" And StringRegExp($iCols, '\A0+[1-9]') Then GUICtrlSetData($hStandardCols, StringRegExpReplace($iCols, '(\A0+)([1-9])(\d+)*', '$2$3')) If $iRows > $iMaxFields Or $iCols > $iMaxFields Or GUICtrlRead($hStandardRows) * GUICtrlRead($hStandardCols) > $iMaxFields Then If Not $bStandardError Then GUICtrlSetBkColor($hStandardRows, 0xFFA090) GUICtrlSetBkColor($hStandardCols, 0xFFA090) $bStandardError = True EndIf ElseIf $bStandardError Then GUICtrlSetBkColor($hStandardRows, 0xFFFFFF) GUICtrlSetBkColor($hStandardCols, 0xFFFFFF) $bStandardError = False EndIf $iCols = GUICtrlRead($hColNum) If ControlGetFocus($hChild) <> "Edit3" And StringRegExp($iCols, '\A0+[1-9]') Then GUICtrlSetData($hColNum, StringRegExpReplace($iCols, '(\A0+)([1-9])(\d+)*', '$2$3')) $iCols = GUICtrlRead($hColNum) If $iCols < 1 Then If BitAND(GUICtrlRead($hCheckBox), $GUI_CHECKED) == $GUI_CHECKED And ControlGetFocus($hChild) <> "Edit3" Then GUICtrlSetData($hColNum, 2) Else GUICtrlSetData($hColNum, 1) EndIf If ControlGetFocus($hChild) = "Edit3" Then _GUICtrlEdit_SetSel($hColNum, 0, -1) EndIf If BitAND(GUICtrlRead($hCheckBox), $GUI_CHECKED) == $GUI_CHECKED Then If $iCols < 2 And ControlGetFocus($hChild) <> "Edit3" Then If ControlGetFocus($hChild) = "Button3" Then While _IsPressed('01') Sleep(20) WEnd EndIf If BitAND(GUICtrlRead($hCheckBox), $GUI_CHECKED) == $GUI_CHECKED Then GUICtrlSetData($hColNum, 2) Else GUICtrlSetData($hColNum, 1) EndIf EndIf Else If $iCols < 1 Then GUICtrlSetData($hColNum, 1) If ControlGetFocus($hChild) = "Edit3" Then _GUICtrlEdit_SetSel($hColNum, 0, -1) EndIf EndIf If $msg2 = $hOkay Then If $bErrorAdv Then MsgBox(262160, "uh-uh!", "Out of Range") ContinueLoop EndIf Local $sDelim = '-' ; read from settings ??? [maybe] If _GUICtrlTab_GetCurFocus($idTab) = 1 Then Local $iName, $sFormat = Default ; read from settings [ini] If BitAND(GUICtrlRead($hCheckBox), $GUI_CHECKED) == $GUI_CHECKED Then $iName = (BitAND(GUICtrlRead($hRadio1), $GUI_CHECKED) == $GUI_CHECKED) ? 3 : 2 Else $iName = -1 EndIf ; $sStartDate, $sStopDate, $sDelim = Default, $sFormat = Default, $iDayName = -1) GetDateArray(GUICtrlRead($idDate1), GUICtrlRead($idDate2), $sDelim, $sFormat, $iName) ; US [, '$3-$5-$1']) EndIf EndIf WEnd GUIDelete($hChild) EndFunc ;==> NewTable Func LocaleDateToYMD($sDate, $sDelim = '/') Local $iID = _WinAPI_GetUserDefaultLCID(), _ $aDateSplit = StringRegExp(_WinAPI_GetLocaleInfo($iID, $LOCALE_SSHORTDATE), '\w+', 3), _ $vTest = True ; [floating variable] If IsArray($aDateSplit) And UBound($aDateSplit) = 3 Then For $i = 0 To 2 ; determine the locale ymd order If StringInStr($aDateSplit[$i], 'y') Then $aDateSplit[$i] = 1 ; year ElseIf StringInStr($aDateSplit[$i], 'm') Then $aDateSplit[$i] = 2 ; month ElseIf StringInStr($aDateSplit[$i], 'd') Then $aDateSplit[$i] = 3 ; day EndIf Next $vTest = $aDateSplit[0] & $aDateSplit[1] & $aDateSplit[2] If StringInStr($vTest, '1') And StringInStr($vTest, '2') And StringInStr($vTest, '3') Then $vTest = False ; success EndIf If $vTest Then ; failure with the previous method [both methods work on Win7 in the UK] Local $sLongDate = _WinAPI_GetDateFormat(0, 0, $DATE_LONGDATE) $aDateSplit = StringRegExp($sLongDate, '(*UCP)\w+', 3) If Not IsArray($aDateSplit) And UBound($aDateSplit) <> 3 Then Return SetError(1) ; undetermined error? For $i = 0 To 2 ; determine the locale ymd order If $aDateSplit[$i] = @YEAR Then ; hopefully this method will work for all international regions $aDateSplit[$i] = 1 ; year ElseIf $aDateSplit[$i] = _DateToMonth(@MON, $DMW_LOCALE_LONGNAME) Then $aDateSplit[$i] = 2 ; month Else $aDateSplit[$i] = 3 ; day EndIf Next $vTest = $aDateSplit[0] & $aDateSplit[1] & $aDateSplit[2] If Not (StringInStr($vTest, '1') And StringInStr($vTest, '2') And StringInStr($vTest, '3')) Then Return SetError(2) ; undetermined error? EndIf Local $iCount = 1, $sYMD = '' Do For $i = 0 To 2 If $aDateSplit[$i] = $iCount Then $sYMD &= '$'& ($i*2 +1) & ($iCount <> 3 ? $sDelim : '') $iCount += 1 ExitLoop EndIf Next Until $iCount = 4 Return StringRegExpReplace($sDate, '(\d+)(\D)(\d+)(\D)(\d+)', $sYMD) EndFunc Func GetDateArray($sStartDate, $sStopDate, $sDelim = Default, $sFormat = Default, $iDayName = -1) Local $iID = _WinAPI_GetUserDefaultLCID(), _ $aDateSplit = StringRegExp(_WinAPI_GetLocaleInfo($iID, $LOCALE_SSHORTDATE), '\w+', 3) If IsArray($aDateSplit) And UBound($aDateSplit) = 3 Then For $i = 0 To 2 ; determine the locale ymd order If StringInStr($aDateSplit[$i], 'y') Then $aDateSplit[$i] = 1 ; year ElseIf StringInStr($aDateSplit[$i], 'm') Then $aDateSplit[$i] = 2 ; month ElseIf StringInStr($aDateSplit[$i], 'd') Then $aDateSplit[$i] = 3 ; day EndIf Next Else ; let's try an alternative method [both methods work on Win7 in the UK] Local $sLongDate = _WinAPI_GetDateFormat(0, 0, $DATE_LONGDATE) $aDateSplit = StringRegExp($sLongDate, '(*UCP)\w+', 3) If Not IsArray($aDateSplit) And UBound($aDateSplit) <> 3 Then Return SetError(1) ; undetermined error? For $i = 0 To 2 ; determine the locale ymd order If $aDateSplit[$i] = @YEAR Then ; hopefully this method will work for all international regions $aDateSplit[$i] = 1 ; year ElseIf $aDateSplit[$i] = _DateToMonth(@MON, $DMW_LOCALE_LONGNAME) Then $aDateSplit[$i] = 2 ; month Else $aDateSplit[$i] = 3 ; day EndIf Next EndIf ; check the array contains numbers 1 to 3 Local $sTest = $aDateSplit[0] & $aDateSplit[1] & $aDateSplit[2] If Not (StringInStr($sTest, '1') And StringInStr($sTest, '2') And StringInStr($sTest, '3')) Then Return SetError(2) ; undetermined error? If $sDelim = Default Then $sDelim = StringRegExp($sStartDate, '\D+', 3)[0] Local $iCount = 1, $sYMD = '' Do For $i = 0 To 2 If $aDateSplit[$i] = $iCount Then $sYMD &= '$'& ($i*2 +1) & ($iCount <> 3 ? $sDelim : '') $iCount += 1 ExitLoop EndIf Next Until $iCount = 4 $sStartDate = StringRegExpReplace($sStartDate, '(\d+)(\D)(\d+)(\D)(\d+)', $sYMD) $aDateSplit = StringRegExp($sStartDate, '\d+', 3) $sStartDate = StringFormat('%04i' & $sDelim & '%02i' & $sDelim & '%02i', $aDateSplit[0], $aDateSplit[1], $aDateSplit[2]) $sStopDate = StringRegExpReplace($sStopDate, '(\d+)(\D)(\d+)(\D)(\d+)', $sYMD) $aDateSplit = StringRegExp($sStopDate, '\d+', 3) $sStopDate = StringFormat('%04i' & $sDelim & '%02i' & $sDelim & '%02i', $aDateSplit[0], $aDateSplit[1], $aDateSplit[2]) Local $vReverse = False If $sStartDate > $sStopDate Then $vReverse = $sStartDate $sStartDate = $sStopDate $sStopDate = $vReverse EndIf ; internal format = yyyy/mm/dd Local $iStartYear = Number(StringRegExp($sStartDate, '\d+', 3)[0]), $iStopYear = Number(StringRegExp($sStopDate, '\d+', 3)[0]) Local $aTimeLine[(($iStopYear - $iStartYear +1) *366)] $iCount = 0 For $iYear = $iStartYear To $iStopYear For $iMon = 1 To 12 Switch $iMon Case 1, 3, 5, 7, 8, 10, 12 For $iDay = 1 To 31 ; this section of code can be shortened $aTimeLine[$iCount] = $iYear & $sDelim & StringFormat('%02i', $iMon) & $sDelim & StringFormat('%02i', $iDay) If $aTimeLine[$iCount] = $sStopDate Then ExitLoop 3 $iCount += 1 Next Case 4, 6, 9, 11 For $iDay = 1 To 30 $aTimeLine[$iCount] = $iYear & $sDelim & StringFormat('%02i', $iMon) & $sDelim & StringFormat('%02i', $iDay) If $aTimeLine[$iCount] = $sStopDate Then ExitLoop 3 $iCount += 1 Next Case Else For $iDay = 1 To IsLeapYear($iYear) ? 29 : 28 $aTimeLine[$iCount] = $iYear & $sDelim & StringFormat('%02i', $iMon) & $sDelim & StringFormat('%02i', $iDay) If $aTimeLine[$iCount] = $sStopDate Then ExitLoop 3 $iCount += 1 Next EndSwitch Next Next ReDim $aTimeLine[$iCount +1] ; get rid of unused elements For $i = 0 To UBound($aTimeLine) -1 If $aTimeLine[$i] = $sStartDate Then _DeleteRegion($aTimeLine, 1, 0, $i) ExitLoop EndIf Next _Predim($aTimeLine, 2) ; add 2nd dimension ; adding a day name column only works for start dates up to christmas day 2999 [millennium bug], is it worth fixing? ==> [FIXED] If $iDayName <> -1 Then ; $iDayName set to -1 because _DateDayOfWeek() format values range from 0 to 3 ReDim $aTimeLine[UBound($aTimeLine)][2] Local $aNextDay, $iDayNum If $sStartDate <= ('2999' & $sDelim & '12' & $sDelim & '25') Then For $i = 0 To 6 If $i = UBound($aTimeLine) Then ExitLoop $aNextDay = StringRegExp($aTimeLine[$i][0], '\d+', 3) $iDayNum = _DateToDayOfWeek (Number($aNextDay[0]), Number($aNextDay[1]), Number($aNextDay[2])) $aTimeLine[$i][1] = _DateDayOfWeek($iDayNum, $iDayName) Next For $i = 7 To UBound($aTimeLine) -1 $aTimeLine[$i][1] = $aTimeLine[Mod($i, 7)][1] Next Else Local $aDayName[7] For $i = 25 To 31 $aNextDay = StringRegExp('2999/12/' & $i, '\d+', 3) $iDayNum = _DateToDayOfWeek (Number($aNextDay[0]), Number($aNextDay[1]), Number($aNextDay[2])) $aDayName[$i -25] = _DateDayOfWeek($iDayNum, $iDayName) Next Local $iDateDiff = DateRange('2999/12/25', StringReplace($aTimeLine[0][0], $sDelim, '/')) For $i = 0 to 6 If $i = UBound($aTimeLine) Then ExitLoop $aTimeLine[$i][1] = $aDayName[Mod($iDateDiff + $i -1, 7)] Next For $i = 7 To UBound($aTimeLine) -1 $aTimeLine[$i][1] = $aTimeLine[Mod($i, 7)][1] Next EndIf EndIf If $sFormat = Default Then ; [regexp pattern stored in ini or settings] $aDateSplit = StringRegExp($sYMD, '\d', 3) _Predim($aDateSplit, 2) ReDim $aDateSplit[3][2] $aDateSplit[0][1] = 1 $aDateSplit[1][1] = 3 $aDateSplit[2][1] = 5 _ArraySort($aDateSplit) $sFormat = '$' & $aDateSplit[0][1] & $sDelim & '$' & $aDateSplit[1][1] & $sDelim & '$' & $aDateSplit[2][1] EndIf For $i = 0 To UBound($aTimeLine) -1 $aTimeLine[$i][0] = StringRegExpReplace($aTimeLine[$i][0], '(\d+)(\D)(\d+)(\D)(\d+)', $sFormat) Next If $vReverse Then _ReverseArray($aTimeLine) _ArrayDisplay($aTimeLine) Return $aTimeLine EndFunc ;==> GetDateArray Func IsLeapYear($iYear) If Mod($iYear, 4) Then Return False ElseIf Mod($iYear, 100) Then Return True ElseIf Mod($iYear, 400) Then Return False Else Return True EndIf EndFunc ;==> IsLeapYear Func DateRange($sDate1, $sDate2) ; must be yyyy/mm/dd Local $vTemp If $sDate1 > $sDate2 Then $vTemp = $sDate1 $sDate1 = $sDate2 $sDate2 = $vTemp EndIf Local $aArray1 = StringRegExp($sDate1, '\d+', 3), $aArray2 = StringRegExp($sDate2, '\d+', 3) For $i = 0 To 2 $aArray1[$i] = Number($aArray1[$i]) $aArray2[$i] = Number($aArray2[$i]) Next Local $iCount = 0 For $i = $aArray1[0] +1 To $aArray2[0] -1 If Not IsLeapYear($i) Then $iCount += 365 Else $iCount += 366 EndIf Next Local $iFirstMonth = 0 Switch $aArray1[1] Case 1, 3, 5, 7, 8, 10, 12 $iFirstMonth = 32 - $aArray1[2] Case 4, 6, 9, 11 $iFirstMonth = 31 - $aArray1[2] Case Else $iFirstMonth = (IsLeapYear($aArray1[0]) ? 30 : 29) - $aArray1[2] EndSwitch If $aArray1[0] < $aArray2[0] Then $iCount += $iFirstMonth For $i = $aArray1[1] +1 to 12 Switch $i Case 1, 3, 5, 7, 8, 10, 12 $iCount += 31 Case 4, 6, 9, 11 $iCount += 30 Case Else $iCount += (IsLeapYear($aArray1[0]) ? 29 : 28) EndSwitch Next $iCount += $aArray2[2] ; add remaining days in final month If $aArray2[1] > 1 Then For $i = 1 To $aArray2[1] -1 Switch $i Case 1, 3, 5, 7, 8, 10, 12 $iCount += 31 Case 4, 6, 9, 11 $iCount += 30 Case Else $iCount += (IsLeapYear($aArray2[0]) ? 29 : 28) EndSwitch Next EndIf ElseIf $aArray1[1] < $aArray2[1] Then ; same year, different month $iCount += $iFirstMonth For $i = $aArray1[1] +1 to $aArray2[1] -1 Switch $i Case 1, 3, 5, 7, 8, 10, 12 $iCount += 31 Case 4, 6, 9, 11 $iCount += 30 Case Else $iCount += (IsLeapYear($aArray1[0]) ? 29 : 28) EndSwitch Next $iCount += $aArray2[2] Else ; same month and year $iCount = $aArray2[2] - $aArray1[2] +1 EndIf Return $iCount EndFunc ;==> DateRange ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Functions from ArrayWorkshop.au3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #Au3Stripper_Off Func _ReverseArray(ByRef $aArray, $iDimension = 1, $iStart = 0, $iEnd = -1) If Not IsArray($aArray) Or UBound($aArray, 0) > 9 Then Return SetError(1) ; not a valid array Local $aBound = __GetBounds($aArray) If @error Then Return SetError(2) ; array contains zero elements $iDimension = ($iDimension = Default) ? 1 : Int($iDimension) If $iDimension < 1 Or $iDimension > $aBound[0] Then Return SetError(3) ; dimension does not exist $iStart = ($iStart = Default) ? 0 : Int($iStart) If $iStart < 0 Or $iStart > $aBound[$iDimension] - 2 Then Return SetError(4) ; meaningless $iStart value $iEnd = ($iEnd = -1 Or $iEnd = Default) ? $aBound[$iDimension] - 1 : Int($iEnd) If $iEnd <= $iStart Or $iEnd >= $aBound[$iDimension] Then Return SetError(5) ; meaningless $iEnd value If $aBound[0] = 1 Then ___Reverse1D($aArray, $iStart, $iEnd) Else $aBound[$iDimension] = 1 Local $aRegion = ___NewArray($aBound) ; to store extracted regions For $i = 1 To $aBound[0] $aBound[$i] -= 1 Next Local $sIndices = __HiddenIndices($aBound[0], $iDimension), $fnFloodFill = __FloodFunc()[$aBound[0]], _ $sTransfer = '$aSource' & $sIndices ; array syntax While $iEnd > $iStart $fnFloodFill($aRegion, $aBound, $iDimension, 0, $iStart, $aArray, $sTransfer) ; extract the current start region $sTransfer = '$aTarget' & $sIndices $fnFloodFill($aArray, $aBound, $iDimension, $iStart, $iEnd, '', $sTransfer) ; overwrite the current start region $sTransfer = '$aSource' & $sIndices $fnFloodFill($aArray, $aBound, $iDimension, $iEnd, 0, $aRegion, $sTransfer) ; overwrite the current end region $iStart += 1 $iEnd -= 1 WEnd EndIf EndFunc ;==>_ReverseArray Func _DeleteRegion(ByRef $aArray, $iDimension = 1, $iSubIndex = 0, $iRange = 1) If Not IsArray($aArray) Then Return SetError(1) Local $aBound = __GetBounds($aArray) ; get the bounds of each dimension If @error Then Return SetError(4) ; $aArray must contain at least one element If $aBound[0] > 9 Then Return SetError(2) ; nine dimension limit $iDimension = ($iDimension = Default) ? 1 : Int($iDimension) If $iDimension > $aBound[0] Or $iDimension < 1 Then Return SetError(3) ; out of bounds dimension $iSubIndex = ($iSubIndex = Default) ? 0 : Int($iSubIndex) If $iSubIndex < 0 Or $iSubIndex > $aBound[$iDimension] - 1 Then Return SetError(5) ; sub-index does not exist in the dimension $iRange = ($iRange = Default) ? 1 : Int($iRange) If $iRange < 1 Then Return SetError(6) ; range must be greater than zero $iRange = ($iSubIndex + $iRange < $aBound[$iDimension]) ? $iRange : $aBound[$iDimension] - $iSubIndex ; corrects for overflow If $iRange = $aBound[$iDimension] Then Return SetError(6) ; deleting the whole region is not currently supported [give reason] $aBound[$iDimension] -= $iRange ; the size of the dimension in the new array If $aBound[0] = 1 Then For $iNext = $iSubIndex To $aBound[$iDimension] - 1 $aArray[$iNext] = $aArray[$iNext + $iRange] Next ReDim $aArray[$aBound[$iDimension]] Return EndIf Local $iMaxIndex = $aBound[$iDimension] - 1 For $i = 1 To $aBound[0] $aBound[$i] -= 1 Next $aBound[$iDimension] = 0 ; set to loop once [one region at a time] Local $iFrom, $sTransfer = '$aTarget' & __HiddenIndices($aBound[0], $iDimension), $fnFloodFill = __FloodFunc()[$aBound[0]] For $iNext = $iSubIndex To $iMaxIndex $iFrom = $iNext + $iRange $fnFloodFill($aArray, $aBound, $iDimension, $iNext, $iFrom, '', $sTransfer) ; overwrite the final [untouched] region Next $aBound[$iDimension] = $iMaxIndex For $i = 1 To $aBound[0] $aBound[$i] += 1 Next __ResetBounds($aArray, $aBound) ; delete remaining indices EndFunc ;==>_DeleteRegion Func _PreDim(ByRef $aArray, $iDimensions, $bPush = False) If Not IsArray($aArray) Then Return SetError(1) $iDimensions = Int($iDimensions) If $iDimensions < 1 Or $iDimensions > 9 Then Return SetError(2) Local $iPreDims = UBound($aArray, 0) ; current number of dimensions If $iPreDims = $iDimensions Then Return ; no change If $iPreDims > 9 Then Return SetError(3) ; too many dimensions Local $aBound = __GetBounds($aArray) ; get the size of each original dimension If @error Then Return SetError(4) ; $aArray must contain at least one element $aBound[0] = $iDimensions ; overwrite this value with the new number of dimensions Local $sTransfer = '[$a[1]][$a[2]][$a[3]][$a[4]][$a[5]][$a[6]][$a[7]][$a[8]][$a[9]]' ; array syntax to be sent to the remote loop region If $bPush Then ; prefix dimensions, or delete from the left Local $iOffset = Abs($iDimensions - $iPreDims) If $iPreDims > $iDimensions Then ; lower dimensions get deleted For $i = 1 To $iDimensions ; shift elements to lower indices $aBound[$i] = $aBound[$i + $iOffset] Next $sTransfer = '$aSource' & StringLeft('[0][0][0][0][0][0][0][0]', $iOffset * 3) & StringLeft($sTransfer, $iDimensions * 7) Else ; lower dimensions are created ReDim $aBound[$iDimensions + 1] ; make space for more dimensions For $i = $iDimensions To $iOffset + 1 Step -1 ; shift elements to higher indices $aBound[$i] = $aBound[$i - $iOffset] Next For $i = 1 To $iOffset ; assign the size of each additional dimension [1][1][1]... etc... $aBound[$i] = 1 Next $sTransfer = '$aSource' & StringMid($sTransfer, 1 + $iOffset * 7, $iPreDims * 7) EndIf Else ; Default behaviour = append dimensions, or delete from the right ReDim $aBound[$iDimensions + 1] ; modify the number of dimensions [according to the new array] For $i = $iPreDims + 1 To $iDimensions ; assign the size of each new dimension ...[1][1][1] etc... $aBound[$i] = 1 Next $sTransfer = '$aSource' & StringLeft($sTransfer, $iPreDims * 7) EndIf ; add or remove dimensions Local $aNewArray = ___NewArray($aBound) For $i = 1 To $iDimensions $aBound[$i] -= 1 ; convert elements to the maximum index value within each dimension Next ; access the remote loop region Local $iSubIndex = 0, $aFloodFill = __FloodFunc() $aFloodFill[$iDimensions]($aNewArray, $aBound, 0, $iSubIndex, '', $aArray, $sTransfer) $aArray = $aNewArray EndFunc ;==>_PreDim Func __GetBounds($aArray, $iHypothetical = 0) Local $iMaxDim = UBound($aArray, 0) Local $aBound[($iHypothetical ? $iHypothetical : $iMaxDim) + 1] ; [or ==> Local $aBound[9]] $aBound[0] = $iMaxDim For $i = 1 To $iMaxDim $aBound[$i] = UBound($aArray, $i) If $aBound[$i] = 0 Then Return SetError(1) Next If $iHypothetical Then For $i = $iMaxDim + 1 To $iHypothetical $aBound[$i] = 1 ; imaginary dimensions Next EndIf Return $aBound EndFunc ;==>__GetBounds Func __HiddenIndices($iBound, $iDimension) Local $sSyntax = '' ; to access elements at their original indices For $i = 1 To $iBound If $i <> $iDimension Then $sSyntax &= '[$a[' & $i & ']]' ; default ==> '$aSource[$iFrom][$a[2]][$a[3]][$a[4]][$a[5]] etc...' Else $sSyntax &= '[$iFrom]' EndIf Next Return $sSyntax EndFunc ;==>__HiddenIndices Func ___NewArray($aBound) Switch $aBound[0] Case 1 Local $aArray[$aBound[1]] Case 2 Local $aArray[$aBound[1]][$aBound[2]] Case 3 Local $aArray[$aBound[1]][$aBound[2]][$aBound[3]] Case 4 Local $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]] Case 5 Local $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]] Case 6 Local $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]][$aBound[6]] Case 7 Local $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]][$aBound[6]][$aBound[7]] Case 8 Local $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]][$aBound[6]][$aBound[7]][$aBound[8]] Case 9 Local $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]][$aBound[6]][$aBound[7]][$aBound[8]][$aBound[9]] EndSwitch Return $aArray EndFunc ;==>___NewArray Func ___Reverse1D(ByRef $aArray, $iStart, $iStop) Local $vTemp While $iStop > $iStart $vTemp = $aArray[$iStart] $aArray[$iStart] = $aArray[$iStop] $aArray[$iStop] = $vTemp $iStart += 1 $iStop -= 1 WEnd EndFunc ;==>___Reverse1D Func __ResetBounds(ByRef $aArray, $aBound) Switch $aBound[0] Case 1 ReDim $aArray[$aBound[1]] Case 2 ReDim $aArray[$aBound[1]][$aBound[2]] Case 3 ReDim $aArray[$aBound[1]][$aBound[2]][$aBound[3]] Case 4 ReDim $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]] Case 5 ReDim $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]] Case 6 ReDim $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]][$aBound[6]] Case 7 ReDim $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]][$aBound[6]][$aBound[7]] Case 8 ReDim $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]][$aBound[6]][$aBound[7]][$aBound[8]] Case 9 ReDim $aArray[$aBound[1]][$aBound[2]][$aBound[3]][$aBound[4]][$aBound[5]][$aBound[6]][$aBound[7]][$aBound[8]][$aBound[9]] EndSwitch EndFunc ;==>__ResetBounds Func __FloodFunc() ; [modified for this demo] Local $aFloodFunc = ['', ___Flood1D, ___Flood2D] ; , ___Flood3D, ___Flood4D, ___Flood5D, ___Flood6D, ___Flood7D, ___Flood8D, ___Flood9D] Return $aFloodFunc EndFunc ;==>__FloodFunc Func ___Flood1D(ByRef $aTarget, $aBound, $iDimension, $iSubIndex, $iFrom, $aSource, $sTransfer) ; [still experimental] #forceref $iDimension, $iFrom, $aSource ; $iDimension would normally not apply here (special case) Local $a[10] = ['', 0, 0, 0, 0, 0, 0, 0, 0, 0] ; loop iteration count [or indices of higher dimensions within the source array] For $a[1] = $iSubIndex To $aBound[1] ; from the start to the bounds of the 1st dimension (special case) ; only one operation is needed in this special case $aTarget[$a[1]] = Execute($sTransfer) ; hidden parameters may appear in the code being executed Next EndFunc ;==>___Flood1D Func ___Flood2D(ByRef $aTarget, $aBound, $iDimension, $iSubIndex, $iFrom, $aSource, $sTransfer) #forceref $iFrom, $aSource ; hidden parameters Local $a[10] = ['', 0, 0, 0, 0, 0, 0, 0, 0, 0] ; loop iteration count [or indices of higher dimensions within the source array] For $a[2] = 0 To $aBound[2] For $a[1] = 0 To $aBound[1] $a[$iDimension] = $iSubIndex ; override the iteration count (fast method) - $a[0] has no influence $aTarget[$a[1]][$a[2]] = Execute($sTransfer) ; hidden parameters may appear in the code being executed Next Next EndFunc ;==>___Flood2D #Au3Stripper_On 12-28-7466|Fri 12-29-7466|Sat 12-30-7466|Sun 12-31-7466|Mon 01-01-7467|Tue 01-02-7467|Wed 01-03-7467|Thu 01-04-7467|Fri 01-05-7467|Sat 01-06-7467|Sun 01-07-7467|Mon Edited October 3, 2016 by czardas iamtheky 1 operator64 ArrayWorkshop
czardas Posted October 4, 2016 Author Posted October 4, 2016 (edited) Taking another look at this today, I see that there may still be some minor issues (I have my suspicions): nothing I can't fix. I noticed various options when playing around with language settings. One of the Simplified Chinese options seemed to work, although I can't read the day name. I may have only installed a limited language set when I installed windows. I haven't exactly accounted for two digit years, but it seems ridiculous that they might appear in a date control which covers almost 10 millennia - who would do something so crazy as that? Delimiters may be longer than a single digit, and not necessarily consistent (a simple regexp tweak will fix this). I only intend to support formats which use Arabic numerals though. Please could someone who was having problems yesterday confirm that the above version now works in the US/Holland. Edited October 4, 2016 by czardas operator64 ArrayWorkshop
l3ill Posted October 4, 2016 Posted October 4, 2016 (edited) New code working fine with English ( U.S. ) Format Win 7 32 Bit (work) edit: not physically in the US... Edited October 4, 2016 by l3ill czardas 1 My Contributions... SnippetBrowser NewSciTE PathFinder Text File Manipulation FTP Connection Tester / INI File - Read, Write, Save & Load Example
czardas Posted October 4, 2016 Author Posted October 4, 2016 (edited) Excellent! I'll play around with it a little, and later I'll post some better organized code along with comments. I have a busy schedule right now, so it might take me a day or two. You have been very helpful. Thanks everyone. Edited October 4, 2016 by czardas operator64 ArrayWorkshop
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now