Is it possible to programmatically open all closed cell groups in a notebook? - cell

There already was the question "Close programmatically all cell groups in Mathematica?"
Strangely the dualized question has not been posed yet: Is it possible to programmatically open all closed cell groups in a notebook?
The reason to rise it now is that using SelectionMove you can select a cell which is part of a closed group. If in the following example the last cell, which will be selected by proper SelectionMove commands, is part of a closed group, it stays invisible in the closed group, despite AutoScroll->True (contrary to the description):
This series of commands selects the last cell in a notebook:
nb = EvaluationNotebook[]; SelectionMove[nb, All, Notebook]
SelectionMove[nb, After, Cell]
SelectionMove[nb, Previous, Cell, AutoScroll -> True]
Which additional command will open the group in which the last cell is contained such that it becomes visible and is selected as the whole cell? (It might be part of several nested groups of cells!)

The clue are the two commands
FrontEndTokenExecute[nb, "ExpandSelection"]
FrontEndTokenExecute[nb, "SelectionOpenAllGroups"]
However, one has to re-apply the method mentioned in my initial post once more after these two commands.
Sample Select Last Celle Programatically.nb
nb = EvaluationNotebook[];
SelectionMove[nb, All, Notebook] (* \
this one selects all cells in this notebook *)
SelectionMove[nb, After, Cell] \
(* this one moves the insertion point below everything *)
SelectionMove[nb, Previous, Cell,
AutoScroll ->
True] (* if the last cell is part of a closed group, the selection stays \
invisible *)
FrontEndTokenExecute[nb, "ExpandSelection"] (* this one \
selects the group enclosing the last cell *)
FrontEndTokenExecute[nb, "SelectionOpenAllGroups"] (* this one opens it *)
\
SelectionMove[nb, After, Cell] \
(* like command 4 steps above, this one moves the insertion point below \
everything *)
SelectionMove[nb, Previous, Cell,
AutoScroll ->
True] (* now it is no longer part of a closed group, therefore it becomes \
visible *)
10 outmost group: Several groups are stacked one ontop the next. All cells groups are closed individually. This is a test case for the program above.
9 intermediate group
8 intermediate group
7 intermediate group
6 intermediate group
5 intermediate group
4 intermediate group
3 intermediate group
2 intermediate group
1 innermost group
f /# Range[3]
{f[1], f[2], f[3]}
(I had this all in a notebook but I found no way to upload it... After copying all this to a notebook, set everything to manual grouping and then nest the cells from the last one one after the other with the next line above it and then close all subgroups.)
The attached notebook shows how it has to be done and it also contains a test example of deeply nested groups of cells at the very end to which the selection goes. However, a proof that this always works and never fails is still missing, since I have neither an "axiomatic" description of ExpandSelection nor of SelectionOpenAllGroups.
I wish there were more links "also see" in the Help system, especially whrer it is about FrontEnd-related functions.

Related

Removing text and only showing a portion of the answer

I'm trying to run an index match that returns some text, but I don't want the full text, just the portion that varies within the set. For example, cell A1 would contain...
[I want to better understand what you did during this visit] During this visit, did the you... (select appropriate answer) [Receive a tour]
A2...
[I want to better understand what you did during this visit] During this visit, did the you... (select appropriate answer) [Meet with the manager]
How would you extract it to just say...
A1 A2
Receive a tour Meet with the manager
The text can vary a lot, sometimes it'll have a second set of square brackets, sometimes not. But one consistency within Google Form data is that the last pair of square brackets is that part that contains the answer that varies. I'd like to get just this text.
...is that the last pair of square brackets is that part that contains the answer that varies. I'd like to get just this text
try this:
=ARRAYFORMULA(IFERROR(REGEXEXTRACT(A1:A, "([^\[]*)\]$")))
or more blunt:
=ARRAYFORMULA(IFERROR(REGEXEXTRACT(A1:A, "\s\[(.*)\]$")))

How to use Calculated Join in Tableau using 1-M relationship and regex_extract

Question 1 - Is Tableau able to use multiple results from from a single line in a REGEXP using the global variable to compare against another table during a Join operation? If no, question 2 is null. If yes...
Question 2 - I'm attempting to join two data sources in Tableau using a regexp in a calculated join because the left table has 1 value in each cell (ie. 64826) and the right table has 4 possible matches in each cell (ie. 00000|00000|21678|64826).
The problem is that my regex stops looking after it finds 1 match (the first of 4 values), and the global variable /g has the opposite effect I expected and eliminates all matches.
I've tried calculated joins on the Data Source tab. I've also tried separating those 4 values into their own columns in worksheets using
regexp_extract_nth. In both cases, regex stops looking after the first result. A Left Join seems to work somewhat, while an Outer Join returns nothing.
REGEXP_EXTRACT([Event Number],'(\d{5})')
REGEXP_EXTRACT_NTH([Event Number],'(?!0{5})(\d{5})',1)
With these examples, regex would match a NULL with the left table even though 64826 is in the right table. I expect the calculated join to return all possible matches from the right set, so there'd be a match on 21678 and on 64826, duplicating rows in the right table like so...
21678 - 00000|00000|21678|64826
64826 - 00000|00000|21678|64826
45245 - 45106|45245|00000|00000
45106 - 45106|45245|00000|00000
Your original expression is just fine, we might want to make sure that we are sending a right command in Tableau, which I'm not so sure, maybe let's try an expression similar to:
\b([^0]....)\b
even just for testing, then maybe let's modify our commands to:
REGEXP_EXTRACT([Event Number], '\b([^0]....)\b')
or:
REGEXP_EXTRACT_NTH([Event Number], '\b([^0]....)\b', 1)
to see what happens. I'm assuming that the desired numbers won't be starting with 0.
Please see the demo here
Reference

How to convert a *.txt file (copy/pasted variables) into a tabular format

I have a bunch of variables (roughly 80) which I copy+paste into my editor (get those variables from a different *.txt file). After this, it looks a bit messy like
ka15 1-2 tre15 3-4 hsha15 5
juso15 6
kl15 7-9 kkjs15 10
but I'd like to have it structured to get a better idea of what's going on inside the code. I also have to strip away the 15 from each variable. Ideally I would get something like
ka 1-2 tre 3-4 hsha 5
juso 6 kl 7-9 kkjs 10
Is there a clever way to achieve this? I am using SAS Enterprise Guide Editor and VSCode but couldn't find a way. For Example, when I find and replace the 15 I would wish I could replace it with a tab, but couldn't find that option in neither editors. Any ideas to get this automated or at least not do everything by hand?
I found a hacky solution to your problem, if anyone finds a better solution, I'll delete mine, but here it goes ¯\_(ツ)_/¯:
1) Copy all content of file(for example I copied yours twice):
ka15 1-2 tre15 3-4 hsha15 5
juso15 6
kl15 7-9 kkjs15 10
ka15 1-2 tre15 3-4 hsha15 5
juso15 6
kl15 7-9 kkjs15 10
2) Ctrl+H and replace all 15 with nothing (leave empty) using Ctrl+Alt+Enter.
3) Ctrl+F and turn Regular expressions in search box. Now type \s to select whitespace and it should select one whitespace after every word. Now select all occurrences with Alt+Enter and press Backspace followed by Enter. This will delete spaces between the words and place one word on one line of code like so:
ka
1-2
tre
3-4
hsha
...
Press Escape to remove multiple cursors.
4) Press Ctrl+F again and in search box type $ sign. This wil select end of every line. Again, press Alt+Enter to select all occurrences a press Space 5-8 times. Notice however that cursors are not properlly aligned. Press Escape to remove multiple cursors.
5) Place cursor a few spaces from a first word. Then, hold Ctrl+Alt+↓ to add multiple cursors below first one. Then, press Shift+End to select all the whitespace to the end of every line and press Delete to delete it. Press Delete again to align all words in one line seperated by n spaces.
6) Unfortunately, I couldn't find regex for the last part. Cursor should be placed after every 6th variable, but I solved it with by placing cursor next to every 7th word and pressing Enter.
I usually don't type too much like this, but I liked the problem you had. It was more puzzle than a problem to me.
I've come up with 3 regex's that will do what you want. In order to run them all sequentially you will need the regreplace extension or similar.
This goes in your settings:
"regreplace.on-save": false,
"regreplace.commands": [
{
"name": "Transform Data to Table Format, step 1",
"regexp": "([a-zA-Z]+|[\\d-]+)(15)?(\\s[\r\n]?)*",
"replace": "$1 \n",
"priority": 1,
},
{
"name": "Transform Data to Table Format, step 2",
"regexp":
"(([\\S-] {6})(.*))|(([\\S-]{2} {5})(.*))|(([\\S-]{3} {4})(.*))|(([\\S-]{4} {3})(.*))",
"replace": "$2$5$8$11",
"priority": 2,
},
{
"name": "Transform Data to Table Format, step 3",
"regexp":
"((.*)\n)((.*)\n)((.*)\n)((.*)\n)((.*)\n)((.*?)(\\s*\\n))",
"replace": "$2$4$6$8$10$12\n",
"priority": 3,
}
],
It creates a rule for each of the three regex steps. All three rules can be run sequentially by running the regreplace.regreplace command. Here is a demo:
The regex's are designed to look good with data items up to 4 characters long but could be easily modified for longer items.
In step 1, increase the number of spaces before the \n in the replace rule to something like 16 or so.
In step 2, you will have to sense the pattern of the regex groups like (([\\S-]{4} {3})(.*) to modify them. A 13 character long variable might require something like (([\\S-]{13} {3})(.*) as the last group and ([\\S-] {15})(.*))as the first in the sequence, etc. modifying all the other groups in order. Let me know if you need help with that.
Step 3 needs no modification unless you want to change how many data items appear on each line - right now there are 3 variables with their data on each line hence 6 groups in that regex.
It does not matter how many data-value pairs are in any row prior to running the command.
[Two items of caution: There should not be any empty lines before the start of the data, although if necessary you could a regex as the first rule to remove empty lines. Empty lines within the data or at the end are not a problem.
Secondly, the extension cannot be run on selected text only so you will have to place your data at the top of an empty file to convert it and then copy it elsewhere if you wish.]
There is also the replace rules extension which works like regreplace but will according to the docs run on a selection only but it didn't work for me here for some unknown reason. It does have a nicer interface though - all regex's could go into a single rule which could then be independently run.

Find all instances where count is less than

I have a big log file which contains IDs. If the ID is present in the log more than 5 times - it's a success. If it's less - I want to know which ID it is.
Ultimately I need a way in Notepad++ that would give me a list of all IDs ([0-9]{10}) where the instance of that is 5 or less.
Is this somehow possible?
Edit: The format of the file is a standard log4j log, so it has a ton of other data. Example (ID in this case is 12345678901234567)
[08-08-2015 02:08:00] [INFO ] Service [329]: Attempting to substitute message ID with 12345678901234567
[08-08-2015 02:08:00] [DEBUG] ParsedBlock [49]: 3296825 => 12345678901234567
[08-08-2015 02:08:00] [DEBUG] LifeCycle [149]: All messages have not yet been sent. Waiting another 2000 milliseconds. [Send: false]
[08-08-2015 02:08:00] [DEBUG] LifeCycle$5 [326]: Running 5, 2592
Since you're in Notepad++ in the first place, you can take advantage of its functionality outside of Search. Be sure you do all this in a copy of the file, not the original, since it makes changes to the file. Since you haven't answered about the format of the file, I'm assuming the file is just the IDs, one on each line.
The first step is to sort the IDs so all the duplicates appear contiguously: Edit -> Line Operations -> Sort Lines As Integers Ascending
Then do this Search/Replace (with Search Mode set to regex):
Search: (\d{17}\r\n)\1{5,}|(\d{17}\r\n)\2*
Replace: $2
You'll be left with only the IDs that occur 5 or fewer times.
Explanation:
The first half of the alternation (\d{17}\r\n)\1{5,} matches any IDs that repeat 6 or more times. The second half (\d{17}\r\n)\2* matches any other IDs, capturing the first instance in group #2. Then the replace puts back that group with $2.

Notepad++ CSV splitting and removing fields

I have a collection of data in a CSV file and I want to manipulate it in so that I only use some of the values in it. example I have:
1,2,3,4,5,6
asd,sdf,dfg,fgh,ghj,hjk
asd,sdf,dfg,fgh,ghj,hjk
asd,sdf,dfg,fgh,ghj,hjk
asd,sdf,dfg,fgh,ghj,hjk
asd,sdf,dfg,fgh,ghj,hjk
what I want to do is use only use a few fields and possibly in a different order
1,4,3
I know notepad++ can break up values and rearrange them using \1,\2,ect but I don't know how I would do it for this.
Notepad++ isn't really a spreadsheet, which would be your easiest approach for this kind of edit after importing a .CSV. However it does have some limited column editing features which make this workable. Two steps are required, which are outlined below.
1) Line up your text:
a) Highlight all the text.
b) Select the TextFX menu,
c) then the TextFX Edit sub-menu,
d) then the "Line up mulitple lines by (,)"
option.
You will now have all your columns aligned on the commas.
2) Delete an individual column:
a) Ensure no text is highlighted.
b) Hold down the [alt] key while selecting the column you wish to delete with the mouse.
c) Press the delete key to delete what you've highlighted.
The above assumes you have the TextFX plugin installed. If I remember right, this comes as standard but if not, you can easily find it and add it from the Plugin Manager.
Here is an example of selecting an aligned column using the alt key and the mouse, taken from the official Notepad++ site:
http://notepad-plus-plus.org/features/column-mode-editing.html
This regular expression will match 6 groups of 0+ non-comma characters for each line:
^([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*)$
You can then replace with your captured groups like so:
\1,\4,\3
RegEx101
Side note:
Someone correct me if I'm wrong. I've been trying to reduce this down to just one repeated capturing group for legibility, but I can't seem to make it work since it only sees this as one capture group:
^([^,]*,?){6}$