Skip to main content

Array / join / substitute

  • December 22, 2017
  • 8 replies
  • 10 views

Forum|alt.badge.img+8

Hi All!

I am trying to build the formula to show working and non workind days of a month in one field

Rules:

  • Field musst have 31 charachters, for 31 days of the Month
  • ā€œNā€ for non working days and ā€œJā€ for days worked

Example:
Max worked on a project on 13th & 15th

Result should be:
NNNNNNNNNNNNJNJNNNNNNNNNNNNNNN

i have a lookup field showing the days worked, and i know this goes something like
Substitute( REPT(ā€œNā€,31), {Days worked}, ā€œNā€,ā€œJā€) but i am just stuck.

thx for any help!

Forum|alt.badge.img+5

You biggest problem will likely be the current inability to create a generalized looping process within Airtable that can then be applied to an array of records. Instead, I suspect you will have to create a formula that explicitly addresses each of 31 days ā€” probably a big ugly nested IF() statement ā€” with each dayā€™s formula checking to see if that day should be flagged as ā€˜Nā€™ or ā€˜Yā€™.

I thought I had put together a day-driven demo somewhere, but it must not have been ready for prime time, as I canā€™t find it anywhere. However, some of the faux bar charts in my Sales CRM Dashboard take a similar approach, and this reply to another post discusses the technique in more detail. The Leads Demo base discussed in this reply may also be of some interes.


Forum|alt.badge.img+17

Anyway, what do you want to achieve? Maybe we could advise in other ways to do it.


Forum|alt.badge.img+8

Thank you so very much for wanting to help!!

itĀ“s about generating a file for the workers health insurance.

one txt field musst contain 31 x ā€œNā€ or ā€œJā€, N for non working days and ā€œJā€ for worked days.

  • have a table with events & dates linked to staff table
  • have set up the rolup und lookfield to find calculate and display working hours and dates

now only thing left is finding out how to substitute the days with ā€œJā€ , creating this ā€œNNNNNNJJNNNā€¦ā€ field

i have this in excel worked out like this:
$E$1:$E$89 = working days
$C$1:$C$89=$C2 = lastname
$D$1:$D$89=$D2 = firstname

{=CONCAT(MID(IF(ISNUMBER(MATCH(ROW(INDIRECT(ā€œ1:31ā€));$E$1:$E$89*($C$1:$C$89=$C2)*($D$1:$D$89=$D2);0));REPT(ā€œJā€;31);REPT(ā€œNā€;31));ROW(INDIRECT(ā€œ1:31ā€));1))}

Thx!


Forum|alt.badge.img+5
Miroslav_Tunjic wrote:

Thank you so very much for wanting to help!!

itĀ“s about generating a file for the workers health insurance.

one txt field musst contain 31 x ā€œNā€ or ā€œJā€, N for non working days and ā€œJā€ for worked days.

  • have a table with events & dates linked to staff table
  • have set up the rolup und lookfield to find calculate and display working hours and dates

now only thing left is finding out how to substitute the days with ā€œJā€ , creating this ā€œNNNNNNJJNNNā€¦ā€ field

i have this in excel worked out like this:
$E$1:$E$89 = working days
$C$1:$C$89=$C2 = lastname
$D$1:$D$89=$D2 = firstname

{=CONCAT(MID(IF(ISNUMBER(MATCH(ROW(INDIRECT(ā€œ1:31ā€));$E$1:$E$89*($C$1:$C$89=$C2)*($D$1:$D$89=$D2);0));REPT(ā€œJā€;31);REPT(ā€œNā€;31));ROW(INDIRECT(ā€œ1:31ā€));1))}

Thx!


Iā€™m so sorry ā€“ I could have sworn I posted this before the holidays. One morning in the shower I had this great idea of using binary encoding to create a 31-bit number that would represent a month of either work or non-work. Assuming x000 0000 0000 0000 0000 0000 0000 0000 represented a month in which no days were worked, all one would have to do would be to encode each day worked as 2^(Day-1), roll up the values with a SUM() aggregation function, and then, on the other end, encode the decimal value in binary, using 'N' for 0 and 'J' for 1. Much more elegant than my original suggestion.

The encoding went like a dream ā€” and then I spent an hour trying to figure out how to generate the binary without the ability to loop. In the end, I fell back to the old stand-by, the ugly nested IF() statement ā€” at which point it made little sense to retain the binary encodingā€¦

Here is a quick demonstration I tossed together. (Hmmmā€¦ maybe thatā€™s why I didnā€™t post this ā€” it doesnā€™t appear I actually finished the base.) In any case, as you add days worked to an individualā€™s record, youā€™ll see the extracted day+ā€™,ā€™ string added and the corresponding ā€˜Nā€™ change to a ā€˜Jā€™. Each month, youā€™ll have to update the [Days Worked] table to reflect the new month, and youā€™re going to want to build in some error checking to guard against someone being paid for working on Frbruary 31. (I also see I left the powers-of-two field, {PoT}, in there for no good reasonā€¦)

Actually, now that I look at it again,m I see this is not an ugly nested IF() statement: It is actually an ugly concatenation of IF() statements. The actual muscle behind the routine starts out something like this:

IF(FIND('01,',DayIndex)=0,'N','J')&
IF(FIND('02,',DayIndex)=0,'N','J')&
IF(FIND('03,',DayIndex)=0,'N','J')&

and continues in such a a manner until it reaches

IF(FIND('29,',DayIndex)=0,'N','J')&
IF(FIND('30,',DayIndex)=0,'N','J')&
IF(FIND('31,',DayIndex)=0,'N','J')

({DayIndex} is a roill-up of the individual day-or-the-month values with an aggregation function of ARRAYJOIN(values)&','. The trailing &',' in the function ā€” which is valid ā€” is to guarantee a match on the last value in the rolled-up array.) (Actually, I just modified it, because it bugged me to see a single comma as the result when no days worked had been entered. The new aggregation function is

IF(COUNTA(DaysWorked)>0,ARRAYJOIN(values)&',',BLANK())

which, amazingly enough, also appears to be valid.)

Again, not a very pretty answer, but one that works!


Forum|alt.badge.img+8
W_Vann_Hall wrote:

Iā€™m so sorry ā€“ I could have sworn I posted this before the holidays. One morning in the shower I had this great idea of using binary encoding to create a 31-bit number that would represent a month of either work or non-work. Assuming x000 0000 0000 0000 0000 0000 0000 0000 represented a month in which no days were worked, all one would have to do would be to encode each day worked as 2^(Day-1), roll up the values with a SUM() aggregation function, and then, on the other end, encode the decimal value in binary, using 'N' for 0 and 'J' for 1. Much more elegant than my original suggestion.

The encoding went like a dream ā€” and then I spent an hour trying to figure out how to generate the binary without the ability to loop. In the end, I fell back to the old stand-by, the ugly nested IF() statement ā€” at which point it made little sense to retain the binary encodingā€¦

Here is a quick demonstration I tossed together. (Hmmmā€¦ maybe thatā€™s why I didnā€™t post this ā€” it doesnā€™t appear I actually finished the base.) In any case, as you add days worked to an individualā€™s record, youā€™ll see the extracted day+ā€™,ā€™ string added and the corresponding ā€˜Nā€™ change to a ā€˜Jā€™. Each month, youā€™ll have to update the [Days Worked] table to reflect the new month, and youā€™re going to want to build in some error checking to guard against someone being paid for working on Frbruary 31. (I also see I left the powers-of-two field, {PoT}, in there for no good reasonā€¦)

Actually, now that I look at it again,m I see this is not an ugly nested IF() statement: It is actually an ugly concatenation of IF() statements. The actual muscle behind the routine starts out something like this:

IF(FIND('01,',DayIndex)=0,'N','J')&
IF(FIND('02,',DayIndex)=0,'N','J')&
IF(FIND('03,',DayIndex)=0,'N','J')&

and continues in such a a manner until it reaches

IF(FIND('29,',DayIndex)=0,'N','J')&
IF(FIND('30,',DayIndex)=0,'N','J')&
IF(FIND('31,',DayIndex)=0,'N','J')

({DayIndex} is a roill-up of the individual day-or-the-month values with an aggregation function of ARRAYJOIN(values)&','. The trailing &',' in the function ā€” which is valid ā€” is to guarantee a match on the last value in the rolled-up array.) (Actually, I just modified it, because it bugged me to see a single comma as the result when no days worked had been entered. The new aggregation function is

IF(COUNTA(DaysWorked)>0,ARRAYJOIN(values)&',',BLANK())

which, amazingly enough, also appears to be valid.)

Again, not a very pretty answer, but one that works!


First of all,
@Elias_Gomez_Sainz
@W_Vann_Hall

THANK YOU!

Second, i think i found a very interesting problem, not unsolvable, just i dont see it :slightly_smiling_face:

I am building a simple Project / Staffing / Timetracking base. Easy!
Now, if i include a payroll to it, it gets interesting.

Here is a preview:

Rules:

  1. you must have time tracking for every one! per project! per day! per shift!
  2. you must be able to export the data on a daily basis, (some guys work today -> csv export -> import somewhere else, finished)
  3. you mujst have MONTHLY sumarry per person to do a payroll
  4. this has to be in the specific form - (@W_Vann_Hall , Thank you!, i am getting there :slightly_smiling_face: )
  5. per law: if someone workes over the midnight, it has to be calculated as two working days, EARNINGS PER DAY!

in a staffing table i have a ā€œtest NNJJā€ view, where i can export data for daily reports, but how do i do the monthly payroll?

first thught was to have the months summed in the staff table so

  • in a table ā€œstaffā€ i trield to rollout the months and working days, works fine, it rolls out all the monts and all the dates ā€¦ but how do i filter it ā€œper monthā€

do i need another table like : if in timetracking table, month = x, then sum working hours? and then do this for every month in every separate collumn?

  • nother thing i dont understand is how to separate two days in the midnight, in a nighshift?

clocking out and in is not an option

sorry, my brain just stopped.

thx!


Forum|alt.badge.img+5
Miroslav_Tunjic wrote:

First of all,
@Elias_Gomez_Sainz
@W_Vann_Hall

THANK YOU!

Second, i think i found a very interesting problem, not unsolvable, just i dont see it :slightly_smiling_face:

I am building a simple Project / Staffing / Timetracking base. Easy!
Now, if i include a payroll to it, it gets interesting.

Here is a preview:

Rules:

  1. you must have time tracking for every one! per project! per day! per shift!
  2. you must be able to export the data on a daily basis, (some guys work today -> csv export -> import somewhere else, finished)
  3. you mujst have MONTHLY sumarry per person to do a payroll
  4. this has to be in the specific form - (@W_Vann_Hall , Thank you!, i am getting there :slightly_smiling_face: )
  5. per law: if someone workes over the midnight, it has to be calculated as two working days, EARNINGS PER DAY!

in a staffing table i have a ā€œtest NNJJā€ view, where i can export data for daily reports, but how do i do the monthly payroll?

first thught was to have the months summed in the staff table so

  • in a table ā€œstaffā€ i trield to rollout the months and working days, works fine, it rolls out all the monts and all the dates ā€¦ but how do i filter it ā€œper monthā€

do i need another table like : if in timetracking table, month = x, then sum working hours? and then do this for every month in every separate collumn?

  • nother thing i dont understand is how to separate two days in the midnight, in a nighshift?

clocking out and in is not an option

sorry, my brain just stopped.

thx!


Iā€™m walking out the door, but Iā€™ll try to get back to you later.

One quick idea, either as monthly calculation, sanity check, budgetary use, whatever: You can quickly arrive at the number of days worked with

LEN(DaysWorkedEncoded)-LEN(SUBSTITUTE(DaysWorkedEncoded,'J','N'))

^---- Note: Suggested formula is incorrect. See next reply.


Forum|alt.badge.img+5
Miroslav_Tunjic wrote:

First of all,
@Elias_Gomez_Sainz
@W_Vann_Hall

THANK YOU!

Second, i think i found a very interesting problem, not unsolvable, just i dont see it :slightly_smiling_face:

I am building a simple Project / Staffing / Timetracking base. Easy!
Now, if i include a payroll to it, it gets interesting.

Here is a preview:

Rules:

  1. you must have time tracking for every one! per project! per day! per shift!
  2. you must be able to export the data on a daily basis, (some guys work today -> csv export -> import somewhere else, finished)
  3. you mujst have MONTHLY sumarry per person to do a payroll
  4. this has to be in the specific form - (@W_Vann_Hall , Thank you!, i am getting there :slightly_smiling_face: )
  5. per law: if someone workes over the midnight, it has to be calculated as two working days, EARNINGS PER DAY!

in a staffing table i have a ā€œtest NNJJā€ view, where i can export data for daily reports, but how do i do the monthly payroll?

first thught was to have the months summed in the staff table so

  • in a table ā€œstaffā€ i trield to rollout the months and working days, works fine, it rolls out all the monts and all the dates ā€¦ but how do i filter it ā€œper monthā€

do i need another table like : if in timetracking table, month = x, then sum working hours? and then do this for every month in every separate collumn?

  • nother thing i dont understand is how to separate two days in the midnight, in a nighshift?

clocking out and in is not an option

sorry, my brain just stopped.

thx!


Well, I see I obviously never walked back in the door. Are you still wrestling with how to extract the information you need? If so, let me know, and Iā€™ll see if I can helpā€¦

ā€¦and, one hopes, do a better job of helping than I did in my last message, which contained an embarrassingly incorrect formula snippet. The code you need to arrive at the number of days worked would actually be

LEN(DaysWorkedEncoded)-LEN(SUBSTITUTE(DaysWorkedEncoded,'J',''))

The one previously provided would always equate to zero (0).


Alexey_Gusev
Forum|alt.badge.img+23

Thatā€™s crazy to answer on topic 7 years ago, but I just found the task interesting, and using ā€˜formula loopingā€™, quickly crafted it.(reacting on strings like ā€˜03,06,19,25ā€™ )
So let it be here.

 

IF(DayIndex, REGEX_REPLACE( REGEX_REPLACE(
 '01N02N03N04N05N06N07N08N09N10N11N12N13N14N15N
 16N17N18N19N20N21N22N23N24N25N26N27N28N29N30N31N',
    '('&SUBSTITUTE(DayIndex,',','N)|(')&')','J'),
'\\d',''))