How do I execute the CTRL + H function in a Microsoft Access query automatically? - vba

I have numbers displayed as Ranges Ex. 3-7 Days or 24-72 Hours. I need to change these to just a number like 168 or 72 so I can ultimately do comparisons or if statements. I know i can just click CTRL H and go through each condition to format the data, but I have been trying to find a way to have this happen through the query. I am very new to Access so I may be thinking about this all wrong. I tried typing this Expr1: Replace("0-4 Hours", "0-4 Hours", "4") in the field and sometimes it asks for a parameter but it just creates a column called Expr1 with the parameter in it. I followed the syntax i found on this site for replace function so i must be way off.

Query is looking for a field named 0-4 Hours which of course it can't find, hence the prompt (which should always happen, not just sometimes so that is a mystery). Correct syntax:
Expr1: Replace([fieldname], "0-4 Hours", "4").
However, this calc result will show only for records that have 0-4 Hours value. Dynamically calculating this for every record should be possible with:
SELECT *, Val(Mid([fieldname], InStr([fieldname], "-")+1)) As Num FROM tablename;
Every record must have value because Null will cause error.
If the unit (Days, Hours, etc) is not same for all records, this gets even more complicated. If Days and Hours are the only units involved and you want to convert all to Hours:
Val(Mid([fieldname], InStr([fieldname], "-")+1)) * IIf(InStr([fieldname],"Days")>0,24,1) As Num
Any more complication and a VBA custom function would likely be required.

Related

Can someone explain the following Essbase code: FIX, #relative

Can someone please explain the below Essbase code to me please? This is my first time looking at any Essbase code and I'm getting a bit confused as to what it is actually doing.
FIX(&Mth, &Yr, &Version,
"Sector1","Sector2", #relative("Source Code",0), #relative("Channel", 0) )
FIX("AccountNo","DepNo")
DATACOPY "1A11"->"A-500" TO "1BCD"->"C-800";
ENDFIX
ENDFIX
From what I have googled the following is my understanding:
Creates a new command block which restricts database calculations to this subset.
Passes the following members into the command to be used:
Mth
Yr
Version
Returns the following fields:
Sector1
Sector2
returns the 0-level members of the Source Code member - meaning it returns the members of the Total Source Code without children (no other dimensions)
returns the 0-level members of the Channel member - meaning it returns the members of the Channel without children (no other dimensions)
Begins a new command block and passes the following members into the command to be used:
AccountNo
DepNo
Copies the range of cells 1A11, A-500 over to the range 1BCD, C-800
The above is what I understand from the oracle documents on each of the functions, but I can't actually figure out what is happening.
Welcome to the world of Essbase; it can be a little daunting at first especially if you're new to the concept of multidimensionality. You are on the right track regarding analyzing your calc script.
Try not to think of the FIX statement as a command block, per se. A FIX is used to select a portion of cells in the cube. Every single piece of data in your cube has a particular address that consists of one member from every dimension, plus the actual data value itself. For instance, a cube with the dimensions Time, Year, Scenario, and Location might have a particular piece of data at Jan->2018->Actual->Washington. The number of possible permutations of data in a cube can quickly get very large. For instance, if you're organization has 4 years of data, 12 months in a year, 100 locations, 10000 accounts, 3 versions, and 10 departments, you are talking about 4 * 12 * 100 * 10000 * 3 * 10 = 1.4 billion different potential addresses (cells) of data – and that's actually fairly small for a cube, as they tend to grow much larger.
That said, FIX statements are used to narrow down the scope of your calculation operation, rather than operating on the ENTIRE cube (all 1.4 billion cells in my hypothetical example), the FIX essentially restricts the calculation to cells that match certain criteria you specify. In this case, the first FIX statement restricts the calculation to a particular month, yr, version, sectors, sources, and channels. Note that the ampersand on Mth, Yr, and Version means that a substitution variable is to be used. This means your server or cube has a substitution variable value set, such as the variable Mth = "Jan" and Yr = "FY2018" and Version might be "Working" or "Final" or something similar. I would guess that Sector1 and Sector2 are possibly two different members from the same dimension. #RELATIVE("Source Code", 0) is a function that finds the level-0 members (leaf/bottom-level members in a dimension, that is, members that do not have children below them) of the specified member.
In other words, the first FIX statement is narrowing the scope of the calculation to a particular month in a particular year in a particular version (as opposed to all months, all years, all versions), and for that particular month/year/version (for either Sector1 or Sector2) it is fixing on all of the level-0/bottom/leaf members in Source Code and Channel dimensions.
The next FIX statement just further narrows the current scope of cells to calculate on in addition to the outer FIX. It's not uncommon to see FIX statements nested like this.
Lastly we get to the part where something actually happens: the DATACOPY. In the given FIX context, this DATACOPY command is saying that for EACH cell in the current FIX, copy values from the source to the destination. DATACOPY is a little more straightforward when it's just DATACOPY "Source" TO "Target" as opposed to using the inter dimensional operator (->)... but this is perhaps more easily understood in terms of the time/year dimensions. For example, imagine the data copy was written like this:
DATACOPY "FY2018"->"Dec" TO "FY2019"->"Jan";
In this DATACOPY I'd be telling Essbase that for the given FIX context I would like to copy values from the end of the year (data values where the year is FY2018 AND the month is Dec) to the beginning of the next year (data values where the year is FY2019 AND the month is Jan). Your DATACOPY is working in a similar fashion, but using cost centers or something else. It all just depends on how the cube is setup.

Access 2013: How to Return All Records With Date Older than X?

My Problem
I have a date field in the table in question. I'm trying to create a query that will only display records where that date field are 120 days old or older.
My Code
Solution Attempt 1
The first solution I tried was simply added criteria to my date field. The criteria formula I used was:
< Date()-120
This removed a few 'random' records leaving me with 714 of my original 905 records. Unfortunately, a quick look through the dates of remaining records in ascending order, it was obvious that I was still getting records more recent that 120 days old.
Based on my 'random' result above, I double checked the format of my field by changing the field to:
DATE: Format([myDtField], "mm/dd/yyyy")
I ran the query again - this reduced the number of records removed, leaving me with 734 of 905 - but my issue persisted - I still had records with dates more recent than 120 old.
Solution Attempt 2
Based on my issues above, I decided to go a different route. This time I created a unique field for my criteria calculation. For the field value I used:
DateDiff: DateDiff("d",[myDtField],Date())
This resulted in values that were very far off from the correct values (ex. a record with a date of yesterday resulted in 43!).
Solution Attempt 3
This was less of a solution and more just troubleshooting, but based on the results I'm getting, I keep thinking my dates aren't being perceived by the system as the date it's displaying (i.e. DateValue() is off compared to displayed value). I spot checked a few of the dates vs their DateValue() and the randomly selected records all seemed to be correct. So again, no luck.
Solution Attempt 4
#Gustov reminded me about the DateValue() function. I've attempted that on the field as well - the field is imported as a text field, thus needs converted to a date value. Similar to the formula Gustov posted, for my field value I used:
DATEDIFF: DateDiff("d",Nz(DateValue([LASTPAYDT]),0),Date())
And then in the criteria I simply used the formula:
>120
This results in the following error:
Data type mismatch in criteria expression
This was probably the closest solution I had, simply because WITHOUT criteria it returns the proper values (i.e. a date of yesterday returned "1", while a date of two days ago returned "2"... etc). So you would think simply limiting records where this field is >120 would work, but then it throws up the error above.
My Question
Does anyone have an idea of how to check if a record field is 120
days old or older?
If either of my above solutions works for question 1, then what might be wrong with my date field that is causing issues if I am going about it the right way?
#Gustov's DateValue() solution is close (i.e. provides the correct values), but adding criteria causes an error. Any solutions?
I'm at a loss. An extra set of eyes on this problem would be greatly appreciated. Thanks!
Hans touches something. If the dates are not dates but text, try this:
Select * From YourTable
Where
IsDate([myDtField])
And
DateDiff("d", DateValue([myDtField]), Date()) > 120
I have tried this and it works, DATAText is the data stored as a text.
SELECT Tabella1.ID, Tabella1.DATAText, Date() AS Espr1
FROM Tabella1
WHERE (cDate(Format(Tabella1.DataText,"yyyy-MM-dd hh:mm:ss")))<Date()-120;

Access Query / Report - Error: This expression is typed incorrectly or it is too complex to be evaluated on calculated field

So after reading 9 posts about the same error on Stack I didn't really find an answer to my problem, hence me posting this question.
So in my Access I have a query that inherits from several other queries. With this query a User can get information with a certain Date range. This data is put in a report where the records are shown and internally (in the report) some calculation is done of the record fields.
The problem is, when A user wants data until the date 2016-4-22 the report shows up fine. Though when the User wants data until the date 2016-4-30 (from day 23 and on it just gives the same errors) the report tries to load but after a while fails with the error:
This expression is typed incorrectly or it is too complex to be evaluated
So this made me test a few things which I have list down below:
First I thought the Query itself or the given WHERE clause were corrupted / not good so I put the Report recordsource with the WHERE clause in a separate test query and executed it. This all worked fine (no errors).
This made me believe that perhaps a single record was corrupted so I went to the date from which on it gave the error (2016-4-23) and checked this record. Nothing weird was found.
Then I thought it could be some field on the report that was giving the error so I removed several fields and after removing a few Calculated Sum(total) fields the error disappeared.
So I created another query and did the Sum in this query as well based on my created test query - this gave the same error.
After these tests I was pretty sure that perhaps the calculated data was just too much to calculate. I also copied the queries data into Excel and did a SUM of the field there as well. The outcome was roughly 15 million. I can hardly imagine that a number of 15 million is too complex to be evaluated...
Besides that, I also tried to create another SUM query on the specific field but with the date based on 2016-4-22 (so the one that initially DID work). But now it also givers the error on this date... So there goes my theory..
Anyone has a clue what is going wrong?
The 'base' query in question is:
SELECT qryOHW6Verdicht.*
, CStr([nummer] & "." & [qryOHW6Verdicht].[positie]) AS NummerPos
, [ArbeidTot]+[MateriaalTot]+[UitbesteedTot] AS Kosten
, CDbl([AangenomenprijsPositie])+CDbl([MeerwerkPrijsPositie]) AS OpdrachtSom
, IIf([nacalculatie],[Kosten],IIf(IsNull([kostenverwacht]),(100-[otwinstpercentage])/100*[opdrachtsom],[kostenverwacht])) AS VerwachteKosten
, IIf([nacalculatie],[kosten],IIf([Kosten]<[VerwachteKosten],[Opdrachtsom]-[VerwachteKosten],[Opdrachtsom]-[Kosten])) AS VerwachteWinst
, [Kosten]-[VerkoopTot] AS WaardeOHW
, DatePart("yyyy",[gereeddatum]) AS GereedJaar
, [OtOverhead]*[VerkoopTot]/100 AS Overhead
, qryVCBoekingenVerdicht.KostenVerwacht
FROM qryOHW6Verdicht LEFT JOIN qryVCBoekingenVerdicht
ON (qryOHW6Verdicht.[Positie] = qryVCBoekingenVerdicht.[Positie])
AND (qryOHW6Verdicht.[Nummer] = qryVCBoekingenVerdicht.[Offerte])
The report opens with the previous query as recordsource and with this WHERE filter:
1=1 AND (Gereeddatum is null OR Gereeddatum>=#2016-4-30# )
AND Project IS NULL AND NOT (WaardeOHW=0 AND Kosten=0) AND GarantieOrder=0
In the report I got a few Calculated fields and one of them that goes wrong is:
=Sum([OpdrachtSom])

Trying to SUM a formula field based on constraints from another field

A little background on the report:
This is a productivity report for our employees working at our business. We determine their productivity based on the duration of the visits with clients. Some of our employees offer group sessions. They charge each client within the group, even though they are only giving, for example, one hour of service, they can bill for 10 hours if there are 10 people in the group. We determine what service they gave by service codes.
So, I have two fields in this formula, a service code field and a duration field.
The duration field is initially a STRING field from the database, even though it only gives number data, so I change it to a numberVar. The service code field is also a string field, and it sometimes does contain characters and numbers.
What I need Crystal Reports to do is take the sum of the duration. However, if the service code is, say, "1000", it must first divide the duration by 3 before summing it. This is where I get caught up.
Here's my code for the duration:
local numbervar num1;
If GroupName ({billing_tx_charge_detail.v_SERVICE_CODE})="1530" then
num1 := ToNumber({billing_tx_charge_detail.v_duration})/3
else num1 := ToNumber({billing_tx_charge_detail.v_duration})
Then I do a separate formula for the sum, named sumDuration:
Sum(#duration)
I get the error that this field cannot be summarized. After searching Google for two days I have found that Crystal cannot summarize fields or formulas involving constants. If I simply say:
local numbervar num1;
num1 := ToNumber({billing_tx_charge_detail.v_duration})
then I can summarize #duration. What am I missing? It has to be something simple, but I'm just not seeing it. Is there a way to create a custom function to accomplish what I am trying to get here? Or is it even simpler than that?
One person suggested creating a SQL command in order to do the calculations before the data gets to the report. I am a SQL newb so I had no idea where to even begin with that.
If you are grouping by Service Code and placing the above formula in the footer you will only be computing {billing_tx_charge_detail.v_duration} for the last record in the group. If you are intending to use the formula and sum the results and place the results in the Service Code footer try the following. (basically remove the reference to group name)
If {billing_tx_charge_detail.v_SERVICE_CODE}) = "1530" then
ToNumber({billing_tx_charge_detail.v_duration})/3 else
ToNumber({billing_tx_charge_detail.v_duration})
You can use variables (num1) if you want to but they are not needed.
You can still use the second formula you referred to and place in the group footer OR you can place the first formula in details section, right click and insert a summary to the group footer. You can also place in the report footer if you need it to total there as well.

Aggregation of an MDX calculated measure when multiple time periods are selected

In my SSAS cube, I've several measures defined in MDX which work fine except in one type of aggregation across time periods. Some don't aggregate (and aren't meant to) but one does aggregate but gives the wrong answers. I can see why, but not what to do to prevent it.
The total highlighted in the Excel screenshot below (damn, not allowed to include an image, reverting to old-fashion table) is the simplest case of what goes wrong. In that example, 23,621 is not the grand total of 5,713 and 6,837.
Active Commitments Acquisitions Net Lost Commitments Growth in Commitments
2009 88,526 13,185 5,713 7,472
2010 92,125 10,436 6,837 3,599
Total 23,621 23,621
Active Commitments works fine. It is calculated for a point in time and should not be aggregated across time periods.
Acquisitions works fine.
[Measures].[Growth in Commitments] = ([Measures].[Active Commitments],[Date Dimension].[Fiscal Year Hierarchy].currentMember) - ([Measures].[Active Commitments],[Date Dimension].[Fiscal Year Hierarchy].prevMember)
[Measures].[Net Lost Commitments] = ([Measures].[Acquisitions] - [Measures].[Growth in Commitments])
What's happening in the screenshot is that the total of Net Lost Commitments is calculated from the total of Acquisitions (23,621) minus the total of Growth in Commitments (which is null).
Aggregation of Net Lost Commitments makes sense and works for non-time dimensions. But I want it to show null when multiple time periods are selected rather than an erroneous value. Note that this is not the same as simply disabling all aggregation on the time dimension. The aggregation of Net Lost Commitment works fine up the time hierarchy -- the screenshot shows correct values for 2009 and 2010, and if you expand to quarters or months you still get correct values. It is only when multiple time periods are selected that the aggregation fails.
So my question is how to change the definition of Net Lost Commitments so that it does not aggregate when multiple time periods are selected, but continues to aggregate across all other dimensions? For instance, is there a way of writing in MDX:
CREATE MEMBER CURRENTCUBE.[Measures].[Net Lost Commitments]
AS (iif([Date Dimension].[Fiscal Year Hierarchy].**MultipleMembersSelected**
, null
, [Measures].[Acquisitions] - [Measures].[Growth in Commitments]))
ADVthanksANCE,
Matt.
A suggestion from another source has solved this for me. I can use --
iif(iserror([Date Dimension].[Fiscal Year Hierarchy].CurrentMember),
, null
, [Measures].[Acquisitions] - [Measures].[Growth in Commitments]))
CurrentMember will return an error when multiple members have been selected.
I didn't understand much of the first part of the question, sorry...but at the end I think you ask how to detect if multiple members from a particular dimension are in use in the MDX.
You can examine either of the two axes as a string, and use that to form a true/false test. Remember you can use VBA functions in Microsoft implementations of MDX.
I suggest InStr(1, SetToStr(StrToSet("Axis(1)")), "whatever") = 0 as a way to craft the first argument of your IIF.
This gets the set of members on axis number one, converts it to a string, and looks to see if a certain string is present (it returns the position of that string within the other). Zero means not found (so it returns true). You may need to use axis zero instead, or maybe check both.
To see if multiple members from the same dimension were used, the test string above would have to be more complicated. You want to know if whatever occurs once or twice. You could test if the first occurance of the string was at the same position as the last occurance (by searching backwards); though that could also mean the string wasn't found at all:
IIF(
InStr(1, bigstring, littlestring) = InStrRev(bigstring, littlestring),
'used once',
'used twice or not at all'
)
I came across this post while researching a solution for my own issue with grand totals of calculated measures over time when filters are involved. I think you could have fixed the calculations instead of suppressing them by using dynamic sets. This worked for me.