Extract line from multi-line cell that starts with specific character - filter

I have a multi-line cell in A2:
and my goal is to:
extract all lines that start with /
remove in-between empty cells.
My formula in cell B2 is:
=(iferror((ARRAYFORMULA(REGEXEXTRACT(SPLIT(A2,CHAR(10)),"^/.*"))),""))
It is extracting all cells that start with / but keeping empty cell between.

See if this works
=filter(split(A2, char(10)&"/"), regexmatch(split(A2, char(10)), "/.+"))
For an arrayformula you could try
=ArrayFormula(SUBSTITUTE(SPLIT(REGEXREPLACE(A2:A10, "(?:^|\n)([A-Z]+)",), char(10)), "/",))
(Change range to suit)

=ARRAYFORMULA(SUBSTITUTE(SPLIT(TRANSPOSE(QUERY(IFERROR(REGEXEXTRACT(TRANSPOSE(
SPLIT(SUBSTITUTE(A2:A, " ", "♦"), CHAR(10))), "^/(.*)")), , 999^99)), " "), "♦", " "))

Related

How to fix the Power query code error for splitting a text column based on a criteria

Split the text values in a column based on the data type of the first character in each record.
I need to have the new (custom) column return the text before the first " " delimiter if the first character of the text is a number, otherwise return "0,".
If Value.Is(Text.Start([ConsumerAddress],1), type number) Then
Text.BeforeDelimiter([ConsumerAddress]," ") else "0,"
I need to have the new (custom) column return the text before the first " " delimiter if the first character of the text is a number, otherwise return "0,".
I don't think Value.Is is quite what you want. I would recommend a try otherwise construction along with Number.FromText like this:
= Table.AddColumn(#"Previous Step", "Custom",
each try Number.FromText(Text.BeforeDelimiter([ConsumerAddress], " "))
otherwise 0
)
If the text before the first space can be converted to a number, then that's what you get. If it can't the Number.FromText throws an error and you get the 0 from the otherwise specification.
Edit: If you want the criterion for the first character only, try this:
= Table.AddColumn(#"Previous Step", "Custom",
each if (try Number.FromText(Text.Start([ConsumerAddress], 1)) otherwise 0) <> 0
then Text.BeforeDelimiter([ConsumerAddress], " ")
else "0"
)
This will return "12b" from "12b Maple St" whereas the first version would return 0 since "12b" can't be converted into a number.

How do I select a random word within a cell?

I want randomly to select a word from a cell that is generated by a form field using the "paragraph" answer option.
In one formula:
=index(split(A1," "),randbetween(1,1+len(A1)-len(substitute(A1," ",""))))
Does not remove punctuation.
Anchor the 1s in A1s (ie > A$1s) and can be copied down to suit (for different choices from the same cell).
Let's say you want to get a random word from a string in cell A1:
Get word count:
A2 =if(A1="","",counta(split(A1," ")))
Get random value between 1 and word count:
A3 =randbetween(1,A2)
Get the random word using the random value:
A4 =index(split(A1, " "),A3)

ReportViewer Expressions , character check

I'd like to know if there is a way to check if there is a comma , in the !field.Value.
I want to make these conversations:
10,5 -> 10,50
900 -> 900,00
To do that, I need to know if there is a comma in the field value and also how many characters are after the comma. Is it possible ?
Look at InStr(), Len(), and IIF(), I think they will get you what you want.
I don't have a way to test this where I am, but basically I think this expression will get you there:
=IIF(InStr(Fields!MyField.Value, ",") > 0,
Fields!MyField.Value & LEFT("000000", (-1 *(2 - (Len(Fields!MyField.Value) - InStr(Fields!MyField.Value, ","))))),
Fields!MyField.Value & ",00")
Here's the basic idea of the script:
If there is a comma in the field,
then add x number of 0s onto the end of the field
where x is 2 - (the length of the field - the position of the ',' in the string) * -1
else just return the field + ",00"

Concatenate rows per group in RDLC report

Is it possible to concatenate rows into single one? Attached image shows what is required. First table is what I get and second table is what I need. It is the same as SUM function but just need to concatenate strings instead of sum calculation.
I am unable to change datasource.
You can use the & operator.
=Exp1 & ", " & Exp2 & ", " & Exp3
This concatenates the three values with dots between them.

Sorting words (not lines) in VIM

The built-in VIM :sort command sorts lines of text. I want to sort words in a single line, e.g. transform the line
b a d c e f
to
a b c d e f
Currently I accomplish this by selecting the line and then using :!tr ' ' '\n' | sort | tr '\n' ' ', but I'm sure there's a better, simpler, quicker way. Is there?
Note that I use bash so if there's a shorter and more elegant bash command for doing this it's also fine.
EDIT: My use-case is that I have a line that says SOME_VARIABLE="one two three four etc" and I want the words in that variable to be sorted, i.e. I want to have SOME_VARIABLE="etc four one three two".
The end result should preferably be mappable to a shortcut key as this is something I find myself needing quite often.
In pure vim, you could do this:
call setline('.', join(sort(split(getline('.'), ' ')), " "))
Edit
To do this so that it works over a range that is less than one line is a little more complicated (this allows either sorting multiple lines individually or sorting part of one line, depending on the visual selection):
command! -nargs=0 -range SortWords call SortWords()
" Add a mapping, go to your string, then press vi",s
" vi" selects everything inside the quotation
" ,s calls the sorting algorithm
vmap ,s :SortWords<CR>
" Normal mode one: ,s to select the string and sort it
nmap ,s vi",s
function! SortWords()
" Get the visual mark points
let StartPosition = getpos("'<")
let EndPosition = getpos("'>")
if StartPosition[0] != EndPosition[0]
echoerr "Range spans multiple buffers"
elseif StartPosition[1] != EndPosition[1]
" This is a multiple line range, probably easiest to work line wise
" This could be made a lot more complicated and sort the whole
" lot, but that would require thoughts on how many
" words/characters on each line, so that can be an exercise for
" the reader!
for LineNum in range(StartPosition[1], EndPosition[1])
call setline(LineNum, join(sort(split(getline('.'), ' ')), " "))
endfor
else
" Single line range, sort words
let CurrentLine = getline(StartPosition[1])
" Split the line into the prefix, the selected bit and the suffix
" The start bit
if StartPosition[2] > 1
let StartOfLine = CurrentLine[:StartPosition[2]-2]
else
let StartOfLine = ""
endif
" The end bit
if EndPosition[2] < len(CurrentLine)
let EndOfLine = CurrentLine[EndPosition[2]:]
else
let EndOfLine = ""
endif
" The middle bit
let BitToSort = CurrentLine[StartPosition[2]-1:EndPosition[2]-1]
" Move spaces at the start of the section to variable StartOfLine
while BitToSort[0] == ' '
let BitToSort = BitToSort[1:]
let StartOfLine .= ' '
endwhile
" Move spaces at the end of the section to variable EndOfLine
while BitToSort[len(BitToSort)-1] == ' '
let BitToSort = BitToSort[:len(BitToSort)-2]
let EndOfLine = ' ' . EndOfLine
endwhile
" Sort the middle bit
let Sorted = join(sort(split(BitToSort, ' ')), ' ')
" Reform the line
let NewLine = StartOfLine . Sorted . EndOfLine
" Write it out
call setline(StartPosition[1], NewLine)
endif
endfunction
Using great ideas from your answers, especially Al's answer, I eventually came up with the following:
:vnoremap <F2> d:execute 'normal i' . join(sort(split(getreg('"'))), ' ')<CR>
This maps the F2 button in visual mode to delete the selected text, split, sort and join it and then re-insert it. When the selection spans multiple lines this will sort the words in all of them and output one sorted line, which I can quickly fix using gqq.
I'll be glad to hear suggestions on how this can be further improved.
Many thanks, I've learned a lot :)
EDIT: Changed '<C-R>"' to getreg('"') to handle text with the char ' in it.
Here's the equivalent in pure vimscript:
:call setline('.',join(sort(split(getline('.'),' ')),' '))
It's no shorter or simpler, but if this is something you do often, you can run it across a range of lines:
:%call setline('.',join(sort(split(getline('.'),' ')),' '))
Or make a command
:command -nargs=0 -range SortLine <line1>,<line2>call setline('.',join(sort(split(getline('.'),' ')),' '))
Which you can use with
:SortLine
:'<,'>SortLine
:%SortLine
etc etc
:!perl -ne '$,=" ";print sort split /\s+/'
Not sure if it requires explanation, but if yes:
perl -ne ''
runs whatever is within '' for every line in input - putting the line in default variable $_.
$,=" ";
Sets list output separator to space. For example:
=> perl -e 'print 1,2,3'
123
=> perl -e '$,=" ";print 1,2,3'
1 2 3
=> perl -e '$,=", ";print 1,2,3'
1, 2, 3
Pretty simple.
print sort split /\s+/
Is shortened version of:
print( sort( split( /\s+/, $_ ) ) )
($_ at the end is default variable).
split - splits $_ to array using given regexp, sort sorts given list, print - prints it.
Maybe you prefer Python:
!python -c "import sys; print(' '.join(sorted(sys.stdin.read().split())))"
Visual select text, and execute this line.
My AdvancedSorters plugin now has a :SortWORDs command that does this (among other sorting-related commands).

Resources