Using backspace - CHR(8) - in Access Query - ms-access

I have a parts management MS Access database. One of the fields is rarely used - it stores whether a part in inventory is actually rare variant of a more common part. Normally the field is used as a suffix to the primary part number and the database generates that in reports while storing the parent part in the database. (One primary database which controls part numbers does not contain any information on the variants, but it's important to store because the storefront database does.)
I've found in some cases the variant is not simply a suffix. In some cases the correct variant part number eliminates a character from the parent part. For example part "3069b" has a variant "3069bpb198". But I found part "30361c" has a variant "30361pb016" which eliminated the "c".
My preferred solution is to encode a backspace character into the field for those variants which require it. Then when i concatenate the parent part number with the variant number, "30361c" & "\bpb016" becomes "30361pb016". However the output I get in my Access query is "30361c□pb016".
The concatenation formulas in the query I've tried are:
PartNum: [pl].[PartID] & [variant] 'returns "30361c\bpb016"
PartNum: Replace([pl].[PartID] & [variant],"\b",Chr(8))
Is what I'm trying to do possible? And if so what am I doing wrong?
I'd really like to avoid having to change the database so the variant contains the full part number instead of a suffix.

How about:
PartNum: left([pl].[PartID],len([pl].[PartID])-1) & [variant]

Well, you might be able to concatenate the backspace, but how and if that will effect the display of the data is a MASSIVE different issue. The use of ctrl-H goes back to the days of green screens, and even the tele-type age. In other words you want a way to optional remove a character, and using ctrl-H with modern GUI and systems that really don't represent a ASCII character steams means that the question is not about how to make ctrl-H work to chop a char, but how can one chop off a character based on some kind of information.
In other words ctr-H is a crazy approach unless you using a ASCII green screen, or say a printer.
I also would not introduce a non printable character into that data, since you can't type that information into a field, and worse yet you thus can't search, sort and deal with that column as data.
It gets even worse. Your business rule is that "some" data in one column is to effect the display of another column!!!! This breaks the relational data model so bad, it is not even funny.
What you need is to add a bit column (true/false). In fact, really what needs to occur is the selection of the first column needs to take into account the 2nd column, and a DIFFERNT choice should have been made here.
Now this trick/idea might have worked 25 years ago when most computers were ASCII, working with green screens, and output to a screen/terminal or even for crazy sakes a teletype machine? Well, then ctrl-H would work.
Modern systems are displaying data in a graphical format, and the data is not really ASCII anymore - but is saved in uni-code. (which allows display in just about any language or region).
Now, assuming that the people who suffered some serious brain damage to consider polluting the data this way?
Well, you could use this function:
Public Function vScrub(ByVal s As Variant) As String
Dim c As Integer
If IsNull(s) Then
vScrub = ""
Exit Function
Else
c = InStr(s, Chr(8))
Do While c <> 0
s = Left(s, c - 2) & Mid(s, c + 1)
c = InStr(s, Chr(8))
Loop
End If
vScrub = s
End Function
So, place the above in a standard code module (not a class module, nor a forms module).
Once done, then any form, any report, and yes even any query can simply wrap the string expression with above
eg:
vScrub([Col1] & [col2])
Edit:
Modify routine to work for multiple chr(8) in the string.

Related

Expression in Textbox not passing value to the table

Obviously I am not an Access expert or I would not be asking this question. I created a small database with several tables. On a form, there are several combo boxes for the user to choose different combinations of medium, paper, sizes, etc. I have already created an expression that returns the correct value I need, but I cannot figure out how to get this value into the correct field on the table to store with the record the form is creating. Below are screen shots of the form and a couple of the tables. I have also included the expression I am using. I need the value that the expression returns to go into tbl1Artwork and populate the ArtWorkSKU field.
Expression:
=Left([PieceName],4) & [cbxArtist].Column & [cbxMedium].Column & [cbxPaperType].Column & [cbxPrintType].Column & [cbxSize].Column
The ArtWorkSKU text box is unbound as I had to type the expression in there. I am not sure if this is the correct way to accomplish the goal. In the tables below, except for the PK, all fields are Short Text.
All guidance is greatly appreciated.
Saving calculated data is usually not necessary and can be risky. Saved value can become 'out of sync' with raw data. Value can be calculated when needed.
Saving calculated data requires code (macro or VBA).
Can be as simple as Me!fieldname = Me.controlname.
Real trick is figuring out what event(s) to put code into. In your case, most likely form BeforeUpdate.
Advise not to use spaces nor punctuation/special characters (underscore only exception) in naming convention. Better would be ArtworkSKU or ArtworkSKUnum or Artwork_SKU_Num.
Create the following function in VBA:
Function UpdateSKU()
Me.ArtWorkSKU = Left(Me.[PieceName],4) & Me.[cbxArtist].Column(3) & _
Me.[cbxMedium].Column(2) & Me.[cbxPaperType].Column(2) & _
Me.[cbxPrintType].Column(2) & Me.[cbxSize].Column(2)
End Function
Then, on the form, update the After Update event property (not vba) of each "feeder" control to:
After Update: =UpdateSKU()

How can I group data by matching identical cells in same column then counting instances of a related column?

data output
I am pretty new to Webi and am having an issue creating a variable. I'm trying to check if there is more than 1 email address for each entity legacy account number and if 1 of the contact names contains "Annual Report". So when I flag each entity legacy account number for no email only the ones without a contact name that contains "Annual Report" will be pulled. In the example above only the yellow groups should be called no email. Right now all of them are being pulled into no email. I have tried using if and match as those are what I am most familiar with. Does anyone have any suggestions?
There are number of ways you could do this. I am going to give an example using two variables, but you could easily combine them into one.
Has No Email Var=If(Match(Upper([Contact EmailAddress]); "NOEMAIL*"); 1; 0)
Annual Report Contact Name Var=If(Match(Upper([Contact Name]); "ANNUAL REPORT*"); 1; 0)
Then you would apply a report filter with two components...
Has No Email Var = 1
AND
Annual Report Contact Name Var = 0
Let me explain a few things...
The purpose of the Upper function is the Match function is case sensitive. If you know your email address are always lower case then you could remove that the Upper function and have it match on "noemail*".
It is significant that I only have a asterisk ("*") at the end of the string being sought. That will only find a match where the corresponding column value starts with that string. If you want it to be true whenever the string is found anywhere in the column being searched you would be asterisks on both ends.
You could also put limiting criteria in your query filter. But here is where thing can get confusing. Within the query filter you can choose the Matches pattern operator. However, the wildcard character is different ("%" rather than "*") and you do not put double-quotes around your search text. So you would have some thing like this...
Contact EmailAddress Matches pattern noemail%
AND
Contact Name Different from pattern Annual Report%
I am sure you noticed I didn't convert the search text to uppercase. In the Query Panel Web Intelligence is case-insensitive and would likely follow the case-sensitivity of the database of the source data. All of our databases are case-insensitive so if yours is case-sensitive you may need to play around this this a bit. Or just go with the approach of creating the variables and report filters as I initially laid out.
If you want a wildcard for a single character rather than multiple characters (which is what "*" and "%" will do) you need to use a "?" within your variable definition or a "_" in your query filter.
Hope this helps,
Noel

MS-Access Web DB "type mismatch" when setting date as string?

This is specifically for MS-Access Web Databases (requires Sharepoint hosting) which has many limitations compared to their client counterparts, like no VBA, instead you get form macros and data macros to manage data.
I've run into a weird bug on one of my applications. I have a query used to check stock levels against a "minimum stock level" also saved in the table. The query is pretty intense and there are over 4,000 records now to check against. These querys normally take about 75s. So I have made a little label that gets updated every time the form is loaded showing the time and date the query was last run, and the duration in seconds it took. (so users can see how fresh the data is and decide if it needs to be run again)
Now, the weird thing is it works fine in my Access client, but when I sync my changes to the server and try it in a web browser I get a "type mismatch" error. A small table is used to store the start and end times whenever the query is run, that's how I get the timestamp data. These fields are in a "Date/Time" format, obviously. But it seems the problem here is changing the date format to a string format so it can be put in a label on the form. The Access client seems perfectly capable of doing this, while the web client stumbles and falls.
My problem is, how do I change data in a date/time format to a string format in a Web database? I can't figure out how to do this. The tools are so limited. I may have to end up answering my own question here but I'm posting this for others just in case.
To return a value from a data macro as string, you have to format the internal date/time format as a string. In Access an internal date/time value is a double number with the integer part as number of days since 1900, and the “decimal” time part is a fraction of 24 hours. Unfortunately if you simply wrap the date/time in the str$() function we had for 20+ years, then you get something JUST like if you type this into the debug window:
? cdbl(now())
41955.5478587963
The solution is to simply pull out each part. And “nice” is while in few cases a data macro will cast the data type, it does in this case and thus the STR$() command is not required.
The expression you thus can use is this:
Month([d]) & "/" & Day([d]) & " Time = " & Hour([d]) & ":" & Minute([d])
So say to pluck out the VERY LAST start time column from say a invoice table, since we don’t have a dmax(), then we simply sort the table in the order we want and pull out the first row.
Our data macro will thus look like:
Note how in above I simply typed in the SQL and SET the order on the date/time column. I want the MOST recent invoice start date and time. For those new to SQL, then I suggest you build a query in the query builder and specify a query in above lookup feature, since many are not "comfortable" typing in free hand SQL as I did above.
Now, in your browser side (UI) macro, you can use this code:
The above returns a formatted string that you can stuff into a text box, or as per above code change the caption of a label.
Unfortunately with silly problems like this, it becomes a path-of-least resistance thing.
Since my intended result was simply to get "a timedatestamp from a table to show up on a form (so users could see when a query was last run)", this became redesigning my form in Access to be a text field instead of a label. Text fields can be adjusted to accept "Time/Date" formats, so this is exactly what I did, it now pulls the timestamp data directly from the last record of the table and requires no extra formatting to appear in the web browser. I redesigned the text field to appear and function more like a label, and my desired function was achieved.
However, since my question specifically asks, "how do you change a time/date format into a string format in a Web db?", I will leave it here in case someone actually does solve it.

MySQL conditional variable inside text field

This might seem like a strange one, but can you store a conditional variable inside a text field (or something that can be made to work like one)?
I'm creating a notification system that groups notification by date and type, so if 2 or more of the same type are created in the same day it will group the notifications together and provide a count (e.g. Person1 and 3 others have done something).
The notification messages are stored in a table as a template e.g.
[[value]] has just done something
[[value]] is then replaced with Person1's name (and count OTHERS) by using
REPLACE(t1.message,
'[[value]]',
IF(t1.value_as_user=1,
CONCAT(t1.forename, ' ', t1.surname, IF((count((t1.id + DATE(t1.date)))-1)<>0,
CONCAT(' and ', (count((t1.id + DATE(t1.date)))-1), ' other'),
'')),
t1.value)) as 'message'
The only problem with this is it would mean that grammatically the message would no longer make sense i.e. "Person1 and 2 others has just done something" should now be "Person1 and 2 others have just done something"
Is there a way to select a string within a text field (like I have done with [[value]]) except have it where it would be something like [[has/have]] and depending on the count the correct one could chosen?
Sometimes you can change the sentence to avoid the grammatical variability:
Something has been done by Person1 and 2 others
(If you read The Elements of Style by Strunk & White, you may be conditioned to recoil at the passive voice. The above trick may seem like cheating. But don't let them bully you.)
Otherwise, no, there's no function in MySQL that can analyze a string and find out its grammatical usage in English and automatically conjugate verbs.
You could make [[has/have]] be another meta-field in your string, and then replace it with another expression based on the count.
But frankly, I wouldn't do the string formatting in an SQL expression. Not only for this reason, but because string-manipulation in SQL is clumsy compared to literally any other language (except Java of course).

Reporting services: Join all field on a dataset

In a report, I've a dataset with a filter(based on a MultiValue parameter).
This dataset contains two field: Id and Name.
I need to display somewhere the concatenation of all names:
Name1 / Name2 / Name3
The problem is that the join method works only on array, and then I cannot specify a dataset as value.
I looked in custom code too, but I didn't found anything working.
How should I do this ?
I may be a bit late for this but for anyone that's interested in this, there is a rather easy way of doing this in SSRS:
=Join(LookupSet(1,1,Fields!Name.Value, "DatasetName")," / ")
SSRS-2008 R2 and higher...
1. Using LookupSet
If you're beyond the 2008 version OP has, there exists a good solution:
=Join(LookupSet(1, 1, Fields!Name.Value, "DatasetName"), " / ")
Credit for this answer using the LookupSet solution goes entirely to #urbanhusky's answer.
SSRS-2008 and lower...
I'm keeping this answer though because it aggregates #urbanhusky's solution with the solutions available to poor souls stuck with OP's version of SSRS and below.
In SSRS 2008 there's only three "options" as far as I can see, each with its own downside. The first one's probably the least hackish.
2. Extra parameter
Create an internal parameter (e.g. "NameParameter", see this SO answer or MSDN) with Allow Multiple Values. Set the default value of the parameter to the Name field from your dataset. Then use the function =Join(Parameters!NameParameter.Value, " / ") to show the joined names in a textbox.
This may be your best bet, but if there are a lot of values the parameter may not work very well.
3. Use a List
Create a List and drag/drop the Name field to it. If necessary, group on the Name as well.
The disadvantage here is that (AFAIK) the list can't be made to show horizontally.
4. Use a Matrix
Oh boy, this one's real ugly. Nonetheless, here goes: create a matrix, drag the Name field to the column header, and hide the first column as well as the second row (for displaying the data).
The main disadvantage is that it's a hack (and quite some overkill), plus you'll have to trim the last seperator character manually with an expression.