
Jokerman
Active Members-
Posts
21 -
Joined
-
Last visited
Everything posted by Jokerman
-
Thanks for replying to mLipok's questions! I've had my face in code almost nonstop since my last reply. Sure, I'd be happy to test for you! Feel free to DM to give instructions or whatever.
- 250 replies
-
- isn autoit studio
- isn
-
(and 3 more)
Tagged with:
-
I'll take your word for it. I haven't looked into the inner-workings of ISN. π
- 250 replies
-
- isn autoit studio
- isn
-
(and 3 more)
Tagged with:
-
TouchΓ©! You're probably right. I'm not very good at showing appreciation to posts I find helpful. It isn't that I'm not appreciative but that I'm forgetful. I'm usually in a rush and often time stressed about not being able to figure something out so I hit the forum in the hope someone else has already run into the same thing - and more often than not someone has. Once I find the solution I jump back into fixing my issue and finishing the project with the intention to go back to give thanks and like posts...but inevitably I end up forgetting. My apologies to you and everyone else who has helped me!
- 250 replies
-
- isn autoit studio
- isn
-
(and 3 more)
Tagged with:
-
Honestly, I don't know if that's an option in Scintilla but it's an option in ISN AutoIt Studio. It's an add-on to highlighting all matches when you highlight something - in addition to highlighting all matches you also get those markers next to each line that has a match in it. It makes scanning through your script for matches much easier visually since you only have to scan the margin for markers instead of scanning each line of code for the highlighted text. Basically, scan the margin for a marker then scan the line for the highlighted text.
- 250 replies
-
- isn autoit studio
- isn
-
(and 3 more)
Tagged with:
-
Question 1: You can get those markers by enabling the "In addition, add a marker to the line" in ISN AutoIt Studio's Settings (after you select "Script Editor" in Navigation it's under "Write settings"). Question 2: The markers not highlighting everything visible is the issue that I ran into (that, until I made the video, I was failing horribly to explain π€£). ISI360 has confirmed the issue so now it'll come down to how they implemented intellimark. You're right - if the code relies heavily on Scintilla's implementation it may not be easily fixable, if at all. But if ISI360's intellimark functionality is custom code (and it may be considering the massive intellimark performance optimization they introduced in 1.13) I have faith ISI360 will figure it out. π€ Btw, huge respect and thanks to you, mLipok. Your posts and guidance have helped me immensely over the years. π
- 250 replies
-
- isn autoit studio
- isn
-
(and 3 more)
Tagged with:
-
https://i.gyazo.com/efd44dbb9c55cf0525e5d68aa49900e7.mp4 Here's a screen recording trying to show what I mean by the intellimark functionality not taking into account folded code (in this case it's a Region but the same thing happens with all folded code). As you can see in the video when I highlight something while at the top of the tab with the Region folded intellimark only highlights/marks down to line 55 but if I scroll down then intellimark higlights/marks down to line 67 - but if the Region isn't folded then intellimark highlights all the visible lines normally. Also, while not shown in the video, if I hit F8 to turn off the bottom debug window then more lines of code get highlighted without scrolling down (line 68) - this is part of what makes me assume the intellimark functionality is working based on the lines visible in ISN Studio's viewport. Basically, it seems to me (and please correct me if I'm wrong) like the intellimark functionality is using an algorithm to try to determine what's in ISN Studio's viewport so it only highlights matches and marks lines as they become visible (rather than processing the entire tab all at once). If my assumption is correct then it seems like the algorithm isn't accounting for any lines of code that are currently folded and have a + next to them you can click to expand them (like comments, Regions, For/If/Switch/Select statements, etc.). Sorry I can't do a better job of describing the issue. If there's anyone reading this who thinks they understand what I'm saying and can describe it better (or speaks fluent German) please don't hesitate to chime in! This is just one of many reasons I'm a coder and not a teacher. π
- 250 replies
-
- isn autoit studio
- isn
-
(and 3 more)
Tagged with:
-
Alright, I can confirm that intellimark does seem to be working after enabling in Settings - I apologize for that rabbit hole (I swear I tested it at least 2-3 times). After further testing it seems like the method you used to optimize the intellimark functionality may be limiting the lookahead to a certain number of lines or characters to take advantage of the fact that stuff offscreen doesn't need to be marked until it's about to become visible (which is a brilliant optimization). Unfortunately, it seems like maybe the line/character lookahead isn't taking into account any folded lines of code. Because of that any tab that has a lot of folded code causes the intellimark functionality to "fall behind" the code currently visible in ISN's viewport. In effect, I need to scroll past (in some cases, like tabs with a lot of folded code, well past) the code I want marked and then scroll back up to the code to see what is marked. This also, in effect, makes it so the code at the bottom of these tabs can never be intellimarked because you can't scroll past the bottom of the code. Let me know if that makes sense or if you need further explanation. Also, thank you for being so responsive and looking into these issues! I really don't know what I would do without ISN Studio. β€οΈ
- 250 replies
-
- isn autoit studio
- isn
-
(and 3 more)
Tagged with:
-
What I meant by that part is that I had already modified the "enable_intelimark" and "intelimark_also_mark_line" (single 'L') lines to "enable_intellimark" and "intellimark_also_mark_line" (double 'L') and re-opened ISN to find the intellimark functionality working in my first tab. When I then opened Settings, modified and saved the intellimark options at that point ISN left my modified "enable_intellimark" and "intellimark_also_mark_line" (double 'L') lines and simply inserted 2 new "enable_intelimark" and "intelimark_also_mark_line" (single 'L') lines lower in the config.ini (simulated in the attached screenshot since I'd already removed the single 'l' lines). Also, as soon as I change the intellimark options in Settings and click "Save and Close" then intellimark stops working completely until I close and re-open ISN Studio (since the working double 'L' lines are still in the config.ini - along with the single 'L' lines). I hope that helps. If it's still too vague please let me know what unclear and I'll try to describe it better or give better details! π
- 250 replies
-
- isn autoit studio
- isn
-
(and 3 more)
Tagged with:
-
Hi @ISI360, First off, thank you for ISN AutoIt Studio! So many great features and it just keeps getting better! I wanted to let you know about an issue I've run into with 1.13 regarding the intellimark functionality. Unfortunately, after installing 1.13 and re-enabling both intellimark options in Settings I found that the functionality wasn't working at all. I tried enabling each different combination of highlighting matches and marking lines but none of them got it to work. After looking through the config.ini I found the following lines: enable_intelimark=true intelimark_also_mark_line=true After closing ISN, manually changing those lines to the following by changing 'intelimark' to 'intellimark', and re-opening ISN the functionality is now working again (and I must add that it's mind-blowingly fast - well done!). enable_intellimark=true intellimark_also_mark_line=true In addition, after changing the settings inside ISN and checking the config.ini I found that my double 'l' lines weren't changed or removed and, instead, the single 'l' lines were simply re-inserted. However, changing the setting inside ISN kills the intellimark functionality until I close and re-open ISN (single 'l' lines do not need to be removed for functionality to return). Between my description and the config.ini examples you probably already know what happened but, if I had to guess, either something weird happened with my installation or you may have changed spellings while massaging the code for the (absolutely massive) speed increase and missed a spot in the code responsible for writing/modifying the config.ini (since reading the config.ini on startup appears to work fine). Not a huge issue for me since I already got it working but I wanted to let you know and try to give you some solid details so hopefully it's a quick and easy fix. For me, at least, with the basically instantaneous highlighting and marking I'll probably never turn the feature off again! There's one other issue I wanted to bring to your attention which is also relatively minor... I use ISN in the layout pictured below and I generally keep the Project Tree/UDF Explorer/To-Do List/etc. side pane minimized. As you can see in the screenshot, with 1.13 when I open Settings then click Save and Close (no need to modify any settings) the UDF Explorer/To-Do List/Log/Notes pane pops out on its own and to minimize it again I have to restore then minimize the entire side pane by clicking the Project Tree label twice. Again, not a huge issue since I rarely open Settings but just something I wanted to bring to your attention. If you're anything like me (and, if ISN AutoIt Studio is any example, I think you are) then you're a stickler for details, take pride in your work, and always like having your stuff be as polished as possible. Once again, fantastic work and thank you so much for such a wonderful program! ISN Studio is a great productivity booster and makes coding both less work and, in turn, far more enjoyable! I wish all the best for you! EDIT: I thought intellimark was working normally but it turns out it's only working correctly for my first 2 tabs and 91 lines into my third tab. Without going through the code I'm at a loss as to what's limiting the intellimark functionality but I wanted to let you know about my latest realization since you might know off the top of your head what it could be.
- 250 replies
-
- isn autoit studio
- isn
-
(and 3 more)
Tagged with:
-
Help with conversion code - (Moved)
Jokerman replied to Jokerman's topic in AutoIt General Help and Support
Wow! Thank you for all the info and advice, jchd! I don't mind the wall of text, particularly when it's pack with as much good stuff as yours. π² Luckily, I do have a little bit of experience with databases (including SQL) so while I have a hard time coming up with the layout and design myself I think I understand (pretty well, anyway lol) what you've described. I've already read through your post a couple of times and downloaded the SQLite Expert installer and your example DB. I think I'm going to simply need to do some playing with what you've given me and add on from there to see what I come up with. I figure once I come up with the final design then I'll create a brand new DB based on the final design so I start from a clean DB after I know not to do the ridiculous stuff I'll no doubt start off doing. π€£ Thank you, again, for the detail and incredible amount of information you provided, jchd! I believe I have a serious amount of work and learning ahead of me! -
Help with conversion code - (Moved)
Jokerman replied to Jokerman's topic in AutoIt General Help and Support
The version which allows strong encryption sounds like a great fit. Obviously, it isn't necessary for the purposes of country and state conversion but it could be key for future feature additions we've been thinking about. I love that it's essentially transparent since, as you know, the single task nature of AutoIt tends to make any type of stall very visible (unless accounted for with something like a progress animation, of course). I get the idea of extracting and re-integrating the database as a resource but I don't think I can take advantage of the idea in our case. Unfortunately, I believe storing a modified database back into the executable will invalidate the digital signature on our executable. However, taking our future plans into account, and that the DB can be encrypted, I think storing the DB externally will be just fine. I'll give a high level view of the current process that data goes through in order to help give some additional insight into how the conversion code is being used. Currently, the way things work is the user imports their data using a standard template which is imported as either XLSX or tab delimited. When imported our software does some validation on the data and converts all countries and states (among other fields) to our internal default of abbreviations to optimize memory and time (I make sure all the Case lines for my Switch statements begin with the abbreviation). All user data is currently held internally in 2D arrays. Once the user selects which apps they want to export to and hit Next our software starts the conversion. At this point we simply loop through the apps 1 by 1, and for each app loop through the profiles 1 by 1, simultaneously a) converting the data to the preferred format for the app currently being converted, and b) placing the formatted data into the correct places in the output variable (for most apps it's a nested array representing a JSON, but for a few it's a simple 2D array if the app needs delimited or XML). For most of the apps we support I have a nested array of configuration data that tells our software how to process that app like which fields need what data and how that data should be formatted. Each of those app processing variables includes which fields are countries or states and whether they need to be full names or abbreviations. When our software reaches one of those fields it basically just plugs the configuration elements from that sub-array into the conversion function passed variables and the conversion function returns the proper format. Right now my main state conversion functions each support a single country and depend on 3 main passed variables - the state being converted, the name of the app currently being converted (in order to determine the correct formatting in case the app has "special needs" like $g__sAppNameA through $g__sAppNameQ above), and $bAbbrev indicating whether to return the abbreviation or the full name. This is the main functionality I want to recreate using another method. I also have a country conversion function to return the correct format using the same 3 passed variables (except country name rather than state name). In addition, I have 2 more functions named _SetStateByCountry() and _SetStateAndCountry() which use the same 3 variables but add 1 more to have both the country and the state passed - these work by calling the already described conversion functions and do exactly what they say. All functions work using Return values except _SetStateAndCountry() which uses ByRef for both the country and state. I don't know if that's what you were looking for but I hope it at least gives you some of the information you need. My apologies for being so database illiterate that I'm not sure how to provide what you're looking for but I've never had a need for databases in the past. Or, probably more accurately, I never knew I had a need for databases in the past. π€£ -
Help with conversion code - (Moved)
Jokerman replied to Jokerman's topic in AutoIt General Help and Support
That's an interesting approach! Unfortunately, I'm not really a database guy so I can't picture how I would best utilize a database for this purpose. Would I be storing a separate conversion for each country/state supported by each application? Or would each individual country be stored in a single table which is queried for all applications? Also, I was trying to avoid having an external file associated with the conversion but I suspect using SQLite would require just that. While that isn't a deal breaker I have to ask about security. Not being a database guy my questions are: How secure is SQLite and/or what measures need to be put in place to make it secure? And if database encryption is employed what kind of a hit does it have on performance (compared to SQLite w/o encryption as well as strictly AutoIt code)? Btw, I have read some of the benefits of using SQLite with AutoIt for quite a few things (many of them by or because of you, jchd!) but I haven't yet delved into those waters yet. It's a little intimidating, and thinking in terms of databases hasn't clicked for me yet. Any advice? Or good example code I can go look at? Thanks again for taking your time out to read and reply! -
Help with conversion code - (Moved)
Jokerman replied to Jokerman's topic in AutoIt General Help and Support
Thank you to all of you for your replies and suggestions! I apologize for having been gone for a while but I've been trying to complete v2 of our software and things have been insane. Things have calmed down a bit (for the moment, at least) so I have some time to look at this again. I like the ideas (and I'm already using and loving ResourcesEx) but I'm not sure how I can incorporate them into the situation I'm dealing with. I'm afraid the example I gave may not have effectively put into perspective just how difficult the situation is. Here's an another example of our conversion functions - this one for Japan prefectures: Func _StateConvertJP($sState, $iProfileNum = -1, $bAbbrev = False, $sAppName = "") ; Setting passed variables if Default was passed If $iProfileNum = Default Then $iProfileNum = -1 If $bAbbrev = Default Then $bAbbrev = False If $sAppName = Default Then $sAppName = "" ; Setting $bAbbrev to false for g__sAppNameA since the rest of the states besides JP are abbreviated If $sAppName = $g__sAppNameA Then $bAbbrev = False ; For the main Switch we need to remove extra spaces from $sState (because of apps like $g__sAppNameO and $g__sAppNameP) ; and force to upper for matching Switch StringUpper( StringStripWS($sState, $STR_STRIPLEADING + $STR_STRIPTRAILING + $STR_STRIPSPACES) ) Case "JP-23", "AICHI", "AICHI-KEN", "AICHI KEN", "ζη₯η", "ζη₯" Switch $sAppName Case $g__sAppNameA, $g__sAppNameB, $g__sAppNameC, $g__sAppNameD, $g__sAppNameE, $g__sAppNameF Return "Aichi" Case $g__sAppNameG, $g__sAppNameH Return "aichi" Case $g__sAppNameI, $g__sAppNameJ Return "Aichi-ken" Case $g__sAppNameK, $g__sAppNameL, $g__sAppNameM, $g__sAppNameN Return "ζη₯η" Case $g__sAppNameO, $g__sAppNameP ; g__sAppNameO and g__sAppNameP need a space in front of the Kanji Return " ζη₯η" Case $g__sAppNameQ ; Needed because g__sAppNameQ requires both formats but in different fields If $bAbbrev Then Return "JP-23" Else Return "ζη₯η" EndIf EndSwitch If Not $bAbbrev Then Return "Aichi" Else Return "JP-23" EndIf Case Else Return SetError(1, $g__eError_UnknownState, $sState) EndSwitch EndFunc ;==> _StateConvertJP() I only included a single prefecture but I think this code better demonstrates just how complicated things are with all the apps we're trying to support conversion for. Some apps require a particular format, some apps need both abbreviations and full names depending on the field. It's really a nightmare. On the upside, because I've used Switch statements throughout the conversion code it's very fast - it just sucks to create and maintain. π Honestly, I don't know if there's a good answer for what I'm trying to accomplish but what I do know is I certainly haven't been able to come up with a good alternative. Thank you again for the suggestions already provided, as well as any possible solutions anyone might come up with in the future! π -
Help with conversion code - (Moved)
Jokerman replied to Jokerman's topic in AutoIt General Help and Support
Apologies @JLogan3o13, I figured since I was looking more for a method than an AutoIt-specific solution the other forum might have been the appropriate location. I guess I was wrong. π -
Are my AutoIt exes really infected?
Jokerman replied to JSThePatriot's topic in AutoIt General Help and Support
@stephensmith You may want to have a look at the Forum Rules post - specifically the 4th bullet point. Most things about games are specifically off-limits on these forums so think carefully before bringing them up. π -
Hello everyone! I have an application that is a conversion tool that converts address files into the correct formatting for 40+ different applications. In the process of converting I need to take into account specific requirements by the particular applications for how things are formatted both in terms of full name vs abbreviation, but also in exact spellings since many of the applications my tool supports don't follow a standard naming scheme (it would be cake if they all just used the ISO 3166:1 and 3166:2 standards!). To add to the fun my tool also supports importing from many of the applications so the function needs to be able to both accept and write multiple formats/spellings. Anyway, because of these particulars I've been running some conversion code that's functional - but long and ugly - and I really need to come up with a better way if at all possible. So far I have worldwide country conversion, as well as state conversion for 21 countries, and that include is already pushing 11k lines. In addition, by necessity my tool's supported conversions (both applications and countries' states) will continue to grow which will, obviously, only continue to make that include ever more unwieldy. The code is pretty straightforward and simple. Not that it's probably necessary but I've included the function header for additional information. I'm open to any and all solutions that can be implemented without a need to actively pull the information from an outside source. Everything will be stored internally but I don't care whether that's in Arrays, JSONs, XML files, a DB accessed from memory/buffer, whatever (although that's my order of preference if I was able to choose π). Anyway, on to the code... ; #FUNCTION# ==================================================================================================================== ; Name ..........: _StateConvertAU ; Description ...: Converts the passed Australia state in $sState to the needed format ; Syntax ........: _StateConvertAU($sState [, $bAbbrev = False [, $sAppName = ""]]) ; Parameters ....: $sState - The state being processed as a String. ; $bAbbrev - [optional] Whether to return the abbreviation instead of the full name as Boolean. Default is False. ; $sAppName - [optional] The name of the app being processed as a String. Default is "". ; Return values .: State name/abbreviation as a String. ; Author ........: Jokerman ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func _StateConvertAU($sState, $bAbbrev = False, $sAppName = "") If $bAbbrev = Default Then $bAbbrev = False If $sAppName = Default Then $sAppName = "" Local $sStateAbbrevExample = "ACT" Local $sStateNameExample = "Australian Capital Territory" Switch StringUpper($sState) Case "ACT", "AUSTRALIAN CAPITAL TERRITORY" Switch $sAppName Case $g__sAppNameRLB Return "ACT" EndSwitch If Not $bAbbrev Then Return "Australian Capital Territory" Else Return "ACT" EndIf Case "NSW", "NEW SOUTH WALES" Switch $sAppName Case $g__sAppNameRLB Return "NSW" EndSwitch If Not $bAbbrev Then Return "New South Wales" Else Return "NSW" EndIf Case "NT", "NORTHERN TERRITORY" Switch $sAppName Case $g__sAppNameRLB Return "NT" EndSwitch If Not $bAbbrev Then Return "Northern Territory" Else Return "NT" EndIf Case "QLD", "QUEENSLAND" Switch $sAppName Case $g__sAppNameRLB Return "QLD" EndSwitch If Not $bAbbrev Then Return "Queensland" Else Return "QLD" EndIf Case "SA", "SOUTH AUSTRALIA" Switch $sAppName Case $g__sAppNameRLB Return "SA" EndSwitch If Not $bAbbrev Then Return "South Australia" Else Return "SA" EndIf Case "TAS", "TASMANIA" Switch $sAppName Case $g__sAppNameRLB Return "TAS" EndSwitch If Not $bAbbrev Then Return "Tasmania" Else Return "TAS" EndIf Case "VIC", "VICTORIA" Switch $sAppName Case $g__sAppNameRLB Return "VIC" EndSwitch If Not $bAbbrev Then Return "Victoria" Else Return "VIC" EndIf Case "WA", "WESTERN AUSTRALIA" Switch $sAppName Case $g__sAppNameRLB Return "WA" EndSwitch If Not $bAbbrev Then Return "Western Australia" Else Return "WA" EndIf Case Else Return SetError(1, $g__eError_UnknownState, $sState) EndSwitch EndFunc ;==> _StateConvertAU() Any help would be greatly appreciated! And if anyone has questions please don't hesitate to ask! At some point I'd like to share the conversion code as a UDF but I don't want to do that unless I know it's accomplishing its goal using the best method possible. Thanks again! Jokerman
-
Are my AutoIt exes really infected?
Jokerman replied to JSThePatriot's topic in AutoIt General Help and Support
To add on to this - if the first version you compile gets flagged try adding a new comment line, or edit an existing one, and compile again. Or add a new unused variable (which you can then comment/uncomment in future attempts at bypassing the AV filter). I've found that changes as small as these can cause a compiled exe to miraculously no longer be flagged. YMMV. -
Are my AutoIt exes really infected?
Jokerman replied to JSThePatriot's topic in AutoIt General Help and Support
I'd like to start by saying that I've experienced pretty much everything that has been mentioned in this thread - quarantined exes for completely innocuous code, compiled exes flagged as infected months or years after they've been sitting idle in an archive folder, the same script being flagged intermittently each time I compile it, you name it. I knew that would be unacceptable if we released our product in that condition so I researched for many days (probably weeks) before our initial release. This is the route we ended up choosing and I honestly couldn't be happier with the results. After we started signing all of our executables using a reputable code signing cert we no longer get flagged by Windows Defender - even using UPX with maximum compression. We've had rare issues with other AV providers but they've been so rare (easily less than 10 total over the past 18 months) it's really been a non-issue. If you already have a corporation setup I highly recommend doing this sooner rather than later. To be upfront, it does have a cost - both in time (generally 1-4 weeks from application to receiving your cert) and money (<$100/year) - but user trust and peace of mind are (very nearly) priceless. Once you have the code signing cert downloaded and installed you can simply add a line to the top of your script to have SciTE automatically sign your newly compiled exe as the final step in the compile process. Something like this: #AutoIt3Wrapper_Run_After=""%ProgramFiles(x86)%\Windows Kits\....\signtool.exe" sign /tr http://timestamp.comodoca.com/?td=sha384 /td SHA384 /a "%out%"" Also, if you have concerns about Windows Defender being reliable and accurate AV software you can let those concerns go. While it's true Windows Defender has had issues in the past, they were in the beginning of Microsoft's attempts at AV and things have improved significantly since then. If you want to check it out for yourself you can Google it or go here: https://www.techspot.com/news/81396-windows-defender-ranked-joint-best-antivirus-program.html (Fyi, up until about 5 years ago I'd been in IT for >20 years doing anywhere from tech support to Windows/Network Admin. In other words, basically dealing with viruses/rootkits/malware/ransomware on a daily basis because of users or customers lacking the wherewithal to not click the link in the email from an unknown source claiming their inheritance is waiting. π€¦ββοΈ) Edit: Btw, in case anyone does want to go this route I can recommend https://www.thesslstore.com/. I'm not affiliated with them in any way except for that's where I purchased our cert from and I can attest that we received it and it works exactly as I've described. We went with the standard Comodo Code Signing cert. The EV certs are more expensive because they require more background evaluation to be done to verify the entity applying for the cert. It may be advantageous in particular circumstances but isn't necessary to simply avoid AV quarantine. Also, the other unmentioned advantage is your exes are now digitally signed. While for most customers this won't make a difference, if you're using your scripts in a corporate environment this may be a major peace-of-mind bonus since it's easy to verify the authenticity of your exes and they have certain assurances the exes haven't been tampered with. π -
Reading/creating/updating/saving XML
Jokerman replied to Jokerman's topic in AutoIt GUI Help and Support
Thanks for the link, Subz. I went over and read through it already. I like the straight XML DOM use. I ended up using the XML UDF almost exclusively for my solution (except for the $oNode_enum.Text on line 12 - it was just too easy lol): Local $aNodeNames = ["field1","field2","field3","field4","field5","field6","field7","field8","optionSetting"] Local $aData = [["name12","email","choice1","choice2","choice3","choice4","choice5","choice7","true"], _ ["name13","email","choice1","choice2","choice3","choice4","choice5","choice7","true"], _ ["name14","email","choice1","choice2","choice3","choice4","choice5","choice7","true"]] ;~ BEGIN Preparation Local $oNodes_coll = _XML_SelectNodes($oXMLDoc, "//Data[dataType='T1']/dataDetails/friendlyName") Local $iNodeCount = @extended Local $aDataTemp[$iNodeCount][UBound($aData, 2)] Local $iNum = 0 For $oNode_enum In $oNodes_coll $aDataTemp[$iNum][0] = $oNode_enum.Text $iNum += 1 Next _ArrayAdd($aDataTemp, $aData) _ArrayDedupe($aDataTemp) _ArrayDelete($aDataTemp, "0-" & $iNodeCount - 1) $aData = $aDataTemp $aDataTemp = 0 ;~ END Preparation ;~ BEGIN Add data to XML Local $aXSI[1][2] = [['xsi:type','Type1']] For $iOuter = 0 To UBound($aData, 1) - 1 _XML_CreateChildWAttr($oXMLDoc, '/ArrayOfData', 'Data') _XML_CreateChildWAttr($oXMLDoc, '//Data[last()]', 'Enabled', Default, 'true') _XML_CreateChildWAttr($oXMLDoc, '//Data[last()]', 'dataType', Default, 'T1') _XML_CreateChildWAttr($oXMLDoc, '//Data[last()]', 'dataDetails', $aXSI) For $iInner = 0 To UBound($aNodeNames) - 2 _XML_CreateChildWAttr($oXMLDoc, '//Data[last()]/dataDetails', $aNodeNames[$iInner], Default, $aData[$iOuter][$iInner]) Next _XML_CreateChildWAttr($oXMLDoc, '//Data[last()]', $aNodeNames[UBound($aNodeNames) - 1], Default, $aData[$iOuter][UBound($aNodeNames) - 1]) Next ;~ END Add data to XML ;~ BEGIN Cleanup Local $sXmlAfterTidy = _XML_Tidy($oXMLDoc, "utf-8", False) $sXMLAfterTidy = StringRegExpReplace($sXMLAfterTidy, "\t", " ") $sXmlAfterTidy = StringRegExpReplace($sXmlAfterTidy, "(\w+)(/>)", "\1 \2") ;~ END Cleanup ;~ My array dedupe func - _ArrayDedupe(ByRef $aArray[, $bReplace = False]) ;~ Deduplicates an array based on the values in $aData[$x][0] keeping either first or last depending on $bReplace Func _ArrayDedupe(ByRef $aArray, $bReplace = False) Local $i = 0 Local $a1 = $aArray Do Local $a2 = _ArrayFindAll($a1, $a1[$i][0]) If $bReplace Then $a2[0] = UBound($a2) - 1 Else _ArrayPush($a2, "0", 1) EndIf _ArrayDelete($a1, $a2 ) $i += 1 Until $i >= UBound($a1) $aArray = $a1 EndFunc I prefer to stay away from COM stuff unless I have to because I've run into code processors in the past (obfuscators and such) that have a hard time deciphering COM objects using ".Method" notation. While I'm past the point of using an obfuscator (for many reasons noted on this forum) I may be running other things on my code like codescanner or codecrypter, and I prefer to avoid as many issues as possible. Feel free to comment on my code. I'm always looking for the best/most efficient way to do things so if anyone has constructive criticism please don't hesitate to let me know. Edit - I almost forgot, don't try to use my _XML_Tidy as is - I extended that function in my XML.au3 to include an additional parameter for whether to keep the "standalone" declaration that's automatically added. The program I'm exporting to doesn't like that parameter. -
Reading/creating/updating/saving XML
Jokerman replied to Jokerman's topic in AutoIt GUI Help and Support
jdelaney, Doh! I knew there would be names I'd forget and you, sir, are certainly one of them! Thank you for so much of the understanding I've gained in using AutoIt due, in no small part, to your excellent advice. I actually have another tab open with your Excel XML UDF that I plan on taking a look at when my current task is complete. I'm curious if the XML Excel files your UDF creates are in any way related or similar to the XML files held within an Excel XLSX file (they're simply compressed files containing XML files). If the UDF can't already, I think with some modification it could likely create standard XLSX files as quickly and easily as Excel XML files. I've already familiarized myself with XPath, as well looked at the Microsoft XML DOM methods on MSDN (I have a tab open for looking up functionality as needed). I was looking more for a general idea of how best to work back and forth from XML to AutoIt array. For instance, if when going from XML to array it's easiest to simply loop through the nodes and rip XML key/value pairs to an array then I have no problem with that. I just know that right now my experience and knowledge when it comes to dealing with objects in general is seriously lacking and I thought there might be a more elegant or efficient way of obtaining the objective. It's fine if there isn't, I just don't know what I don't know. Thank you for the example, Subz! I love the varied uses of the DOM object directly. Combined with examining how the XML UDF internally handles XML objects I think I have pretty much everything I need code-wise for dealing with the XML DOM. From what I can tell it's going to be best if I use For...In loops combined with With...EndWith statements (wherever it makes sense, of course) for readability and shorter coding. If that's incorrect, or you have additional thoughts, please feel free to let me know! Earthshine - I'm not sure what you posted since I didn't get to read it before you edited but thank you for your reply, as well! Thank you, all. I appreciate you taking time out of your day to provide me with assistance! -
First off, I finally created an account and I'd like to thank all of the wonderful people on this forum who have helped me immensely through the years without even knowing it. I've been coming here for over a decade, on and off, as I've found needs for automation in my various IT positions. I'd love to call everyone out but there are far too many! With that said, in no particular order, I'd like to extend special thanks to Melba23, Jos, guinness, RTFC, trancexx, mLipok, Eltorro, UEZ, Valuater and Ward. It seems like every time I run across a particularly insightful or informative thread I also find at least one or your names - either posting or referred to a previous post as the solution. You know your stuff and it's obvious you deeply care for the community and helping people. While you'll likely never hear it from nearly the number of people that you benefit from your advice, I just wanted to make sure you know there are a TON of appreciative people out there who've never expressed it directly. So, my issue at this point is I'm having a hard time wrapping my head around the best way to deal with XML. While code is always highly descriptive, I'm mostly looking for a medium- to high-level overview of how you would tackle this problem using the XML UDF last updated by mLipok (1.1.1.13)... Here's my XML file - data.xml: <?xml version="1.0" encoding="utf-8"?> <ArrayOfData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Data> <Enabled>true</Enabled> <dataType>T1</dataType> <dataDetails xsi:type="Type1"> <field1>name1</field1> <field2>email1</field2> <field3>choice1</field3> <field4>choice2</field4> <field5>choice3</field5> <field6>choice4</field6> <field7>choice5</field7> <field8>choice7</field8> </dataDetails> <optionSetting>true</optionSetting> </Data> <Data> <Enabled>true</Enabled> <dataType>T1</dataType> <dataDetails xsi:type="Type1"> <field1>name2</field1> <field2>email2</field2> <field3>choice1</field3> <field4>choice2</field4> <field5>choice3</field5> <field6>choice4</field6> <field7>choice5</field7> <field8>choice7</field8> </dataDetails> <optionSetting>true</optionSetting> </Data> <Data> <Enabled>true</Enabled> <dataType>T2</dataType> <dataDetails xsi:type="Type2"> <field1>name3</field1> <field2>email3</field2> <field6>choice6</field6> <field8>choice7</field8> </dataDetails> <optionSetting>true</optionSetting> </Data> <Data> <Enabled>true</Enabled> <dataType>T1</dataType> <dataDetails xsi:type="Type1"> <field1>name4</field1> <field2>email4</field2> <field3>choice1</field3> <field4>choice2</field4> <field5>choice3</field5> <field6>choice4</field6> <field7>choice5</field7> <field8>choice7</field8> </dataDetails> <optionSetting>true</optionSetting> </Data> </ArrayOfData> I also have an AutoIt 2D array ($aNewData[$x][2] = [["name5"][$aName5],["name6"][$aName6],["name7"][$aName7]]) filled with 2D arrays containing data that needs to be entered. I want to open the XML file (data.xml) as an object, check the T1>field1 values against the values in $aNewData[$x][0], populate any non-duplicates from ($aNewData[$x][1])[$y][$z] into the XML object, and save that XML object. Before modifying data.xml I need to make a backup - I have a backup function but I'm unsure when initial modification of the XML takes place so I don't know at what point I need to make a backup (I like to make it right before the point of modification so it only happens if/when the file is actually going to be changed). Also, if the file is blank or missing I need to create it from scratch and then populate with the values from ($aNewData[$x][1])[$y][$z]. Important information: I need nothing from the T2/Type2 nodes but they must remain in place if they exist. There are actually 30+ child nodes of dataDetails that are uniquely named and, while not named sequentially like my example shows, they are in a specific order that's dependent on "dataType" (T1/T2). "field1" is the only node value that cannot have duplicated values. A second feature I need to include is the ability to import the data from data.xml and be able to easily manipulate it. I'm already dealing with several formats and the common denominator is AutoIt arrays - I currently import all data into arrays, manipulate as needed, and then format those arrays out to the required type (Send/ControlSend/Clipboard/JSON/etc). So, based on that and using my example data.xml, what would the best/most efficient way to read all of the "field#" key/value pairs into an AutoIt array? As far as my experience with the XML UDF - it's very little. I've done some playing with the examples provided with the XML UDF, and I believe I have a basic understanding of how it work, but any tips/tricks/gotchas would be greatly appreciated. To any who've made it this far - thank you for taking the time to read through my issue! Sorry, I know it's long but I wanted to try to avoid the mistakes made by so many in their first posts (incorrect or lack of information, trying to fix a symptom rather than a solution to reach the goal, etc). But if I failed that objective and you need further information, please don't hesitate to ask. Thanks again! I'm looking forward to any assistance or information anyone can provide! data.xml