I am attempting to maintain and fix a horribly out-of-date CRM designed by an ex-employee ~4-5 years ago in Access 2007. I have brought it into Access 2013 and fixed a ton of stuff up, but I am still running into many problems.
I spent a good 4 hours today attempting to figure out why certain values didn't line up. These values were being pulled from a SELECT statement on a Combo Box over a stored Query which simply returns a table with a few extra rows. Great.
However this value (a number) doesn't appear to correlate with what we expect. I enter in one value, save the ticket, and a completely different value gets stored into the table. Opening up the ticket, I see the value that I expect. Digging deeper, I found the following difference:
Set value_1 = Me.RegistrationID // What's being stored in the table
Set value_2 = Me.RegistrationID.Column(0) // What we expect
Surprise surprise! This is a Combo Box and some value is being stored in the table. The Control Source is "RegistrationID" and the Row Source is the query in question.
However I do not know what it is! This specific value correlating to the Combo Box appears to pull the correct data when we later open the tickets. However I have a strong feeling that this could be why many tickets from before one of the rows was deleted all appear to have invalid RegistrationID's.
How badly can this break?
How easily can we correct tens of thousands of tickets?
How can I fix this to store the correct value?
This is what I expect is happening.
Your combo box row source is based on a Select query which returns and displays multiple rows. For example:
Select RegistrationID, CustomerID, CustomerName From MyTable;
The Control Source for the combo box is bound to RegistrationID which is part of the Forms Record Source.
The issue is the bound column. If we set the bound column in our example to 1, then we get the behavior your are describing with:
Set value_1 = Me.RegistrationID - Set's value to CustomerID (may appear correct)
Set value_2 = Me.RegistrationID.Column(0) - position 0 from our query (RegistrationID)
Further building on our query example, you can say:
Me.TextBox1 = Me.RegistrationID.Column(0) - RegistrationID
Me.TextBox2 = Me.RegistrationID.Column(1) - CustomerID
Me.TextBox3 = Me.RegistrationID.Column(2) - CustomerName
The RegistrationID is what normally should be stored in the table.
As long as your form shows any values that directly relate to this RegistrationID you're fine.
I would start by checking to see under the format setting to see if column widths are set properly and I would also check under the data section to see if the bound column is correct. I might also throw in an after update macro/vba sub routine that saves the record. Hope this helps.
Related
I need to export my SSRS report to csv format. Issue I am facing is that few column header names change with country code (parameter) and I want to show the same name in my exported csv. I have gone through other related questions and topic, specifically this one. It suggested that there is a work around by setting data value to null. I have tried this by adding columns and hiding these based on country code, along with setting data value to null for that dataset field. But it did not work. I still get the hidden column in my export, with no values in it.
Can someone confirm that this workaround works or is there any other way apart from creating different reports for each country?
UPDATE: (added report screenshot and description for clarification)
Based on apporoach I have taken,
I need to only show Column 'Town' for Country A and only 'Suburb' for Country B. This is easily done by hiding columns based on Country Parameter( and works fine for EXCEL export), but when exported to CSV, both columns are exported.
UPDATE 2
Found this link which is similar to what I have been trying to figure out and looks like there is no solution which can be achieved using only one report.
According to this post
MSDN Social: Hide CSV columns conditionally in SSRS report
The XML and CSV renderers use the DataElementOutput property to
control visibility. We can select which item we want to hide in the
report, and set the “DataElementOutput” property with value “NoOutput”
to work around the issue.
Alternatively, we can add below expression to control the item’s
visibility. Please refer to the expression below:
=IIF(Globals!RenderFormat.Name="CSV",True,False)
This, incidentally, is the second answer in the thread that you posted. That answer links to the following article which explains how to do exactly what you need
Hide/Show Items Dependant On Export Format
UPDATE
It appears that you cannot programmatically set DataElementOutput for CSVs. However, according to this post SSRS - Programatically controlling the DataElementOutput property
in RS 2005 / 2008, you should be able to get the desired effect by adding a filter on the tablix directly (in addition to the visibility condition):
Filter expression: =(Parameters!DataPeriod.Value = "DAY")
Filter operator: =
Filter value: =true
Thereby, for the cases where the tablix is not visible, you are also filtering out all the data.
You may be able to show/hide country specific columns this way instead.
My approach would be to do this in SQL. I'm not sure how you determine which Countries require the town to be returned and which require the suburb to be returned but here's a couple of approaches that hopefully cover your scenario.
In either case, the idea is to return the town/suburb data in the same column and then an additional column that will contain a a caption that we can use as the column header.
a. Only one of either the town or suburb column in your table is populated. In this case it's pretty simple.
SELECT
Country
, ISNULL(TownOrCity, StreetSuburb) AS TownSuburb
, CASE WHEN TownOrCity IS NULL THEN 'Street-Suburb' ELSE 'Town-City' END AS Caption
FROM myTable
b. You know upfront which Countries require what and you can pass a parameter in to get the correct column. In this example we'll use a parameter called #TS and pass in either a T or and S
SELECT
Country
, CASE #TS WHEN 'T' THEN TownOrCity ELSE StreetSuburb END as TownSuburb
, CASE #TS WHEN 'T' THEN 'Town-City' ELSE 'Street-Suburb' END AS Caption
FROM myTable
Whichever approach we take you will end up with a simple table
Country TownSuburb Caption
Testland TownA Town
Testland TownB Town
Testland TownC Town
In you report, you don;t need to do anything except make the town/suburb column caption an expression something like =FIRST(Fields!Caption.Value)
That's it, the report is now nice and simple and should export without any issues.
UPDATE to method:
--
-- Dump data into a temp table
--
SELECT
Country
, CASE #TS WHEN 'T' THEN TownOrCity ELSE StreetSuburb END as TownSuburb
INTO #t
FROM myTable
--
--rename the column
--
DECLARE #NewColumnname sysname = CASE #TS WHEN 'T' THEN N'Town-City' ELSE N'Street-Suburb' END
EXECUTE tempdb..sp_rename N'tempdb..#t.[TownSuburb]', #NewColumnname, 'COLUMN'
--
-- finally get the result
--
SELECT * FROM #t
I have a field with a customer ID that should be in the format of C0000000001, where it has a letter at the start and up to 10 numbers after the letter with leading zeros between the letter and the number. I want the users to be able to put in C1 and have the table save C0000000001 or C1234 and have the table save C0000001234.
I want the restriction to be on the hard data in the table. The table should contain the full customer ID but I only want the users to have to enter the C and the number of the customer when entering/searching for customers. I am using Access 2010.
I believe that the first character will always be a C, but either way, it would only be one alpha character if it wasn't.
I understand what you are saying, but the majority of the data (thousands of records) are going to be from another system that stores them that way. Doing it this way limits my margin of error. Otherwise, exports from the other system will need to be manually changed prior to being imported into the database and vice versa.
Searching would only be on existing records that will be saved in the C0000001234 format, but I would like user to be able to omit the leading zeros when entering the search criteria.
This question, combined with your previous question here, suggest to me that you are trying very hard to have the data structure in your Access database exactly match the legacy system from which you receive bulk updates. That may not be necessary, or even desirable.
For example, instead of maintaining the CustomerId as Text(11) (as in the old system) you could store it in your Access database as
CustomerIdPrefix: Text(1), and
CustomerIdNumber: Long Integer or perhaps Decimal if the numeric part really can exceed 2,147,483,647
Your Customers table in Access could also include a calculated field named CustomerId as
[CustomerIdPrefix] & Right("0000000000" & [CustomerIdNumber], 10)
to give you a single 'C0000012345' value for display purposes.
For searching, your form could have a Text Box for the Prefix (default value: 'C') and another text box for the numeric part. The search could then use a condition like
[CustomerIdPrefix] = txtPrefix.Value AND [CustomerIdNumber] = txtNumber.Value
or, if the user wanted to create a Filter on the Form (or Datasheet View) it would probably be sufficient to just filter on the number part.
If you ever needed to feed information back to the legacy system you could just export a query that includes the [CustomerId] calculated field (and omits [CustomerIdPrefix] and [CustomerIdNumber]) and you'd be fine.
My suggestion would be to use forms with associated queries using the FORMAT function.
You do need to clarify where you want this implemented, but I'm going to assume you have a table set up and that you would like to be able to enter/search data from a form.
I'll create one form for input frmAdd. For the input form, I created a query that would run when a button on the form was pressed. Add two text boxes newID and newOther to the forms which are unbounded but which the user can use to enter data. The query will then pull that data and append it to your table in an altered format. Here's the SQL for that query:
INSERT INTO Customers ( [Customer ID], [Other Field] )
SELECT Left([Forms]![frmAdd]![newID].[value],1)
& Format(Right([Forms]![frmAdd]![newID].[value],Len([Forms]![frmAdd]![newID].[value])-1),"0000000000")
AS Expr1, Forms![frmAdd]!newOther AS Expr2
FROM Customers;
I'm not sure exactly what search functionality you're looking for, but this query would pull up the record data matching that of a frmSearch with a textbox search which would have the format C### or whatever entered in:
SELECT Left([Customers].[Customer ID],1) & Replace(LTrim(Replace(Right([Customers].[Customer ID],9),'0',' ')),' ','0')
AS Expr1, Customers.[Other Field]
FROM Customers
WHERE (((Customers.[Customer ID])=Left([Forms]![frmSearch]![search].[value],1)
& Format(Right([Forms]![frmSearch]![search].[value],Len([Forms]![frmSearch]![search].[value])-1),"0000000000")));
Applying the input mask is just a way to ensure that your data is correct. If you feel the need to use one, go to the table in Design View and click on the Data Type box for the customer ID field. Find Input Mask under Field Properties -> General and click it. Then hit go to the toolbar -> Design tab -> Builder. This will walk you through it.
Input mask is not the answer for this. Input mask forces the user to input the data in a certain manner. What you need is some VBA code to run in the AfterUpdate event on a form. There's no way within the table to force the data into this pattern allowing the input method that you've requested.
There may be a more efficient way to do this, but this does the job.
http://pineboxsolutions.com/access/customeriddemo.accdb
So, I have a problem in Report Builder that is just driving me absolutely crazy.
I have two dataset; one called DS_Grades and the other DS_Pupils. I want to do a simple LookUp based on PupilID, a field that is in both datasets, and return a grade from DS_Grades into a Matrix based on DS_Pupils.
The formula I am using is:
=LookUp(Fields!PupilID.Value, Fields!PupilID.Value, Fields!Grade.Value, "DS_Grades")
I have confirmed that:
1) DS_Grades has the right PupilIds
2) There are actually values in the Grades field
3) Both PupilID fields (I.E. in both datasets) are definitely Integers and not text.
Moreover, if I add a calculated field to DS_Grades called "test" and populated with the value 208301, which is a valid PupilID, then I can enter the below formula and it works fine:
=LookUp(208301, Fields!test.Value, Fields!Grade.Value, "DS_Grades")
So, the LookUp itself must be matching properly, which means that the PupilID fields must be causing the problem, but I have quintuple freaking checked them and they definitely have the right values, in the right format. I am at a total loss as to why SSRS thinks that they don't match.
Help please!
Got it! Some filtering was at Dataset Level (instead of query where I normally do it) that was throwing the whole thing out of joint. Removed that, and it's fine.
I was able to display data from my MySQL table using this code:
datardr = cmd.ExecuteReader
If datardr.HasRows Then
datardr.Read()
tb_lname.Text = datardr("SURNAME")
tb_fname.Text = datardr("GIVEN")
tb_mname.Text = datardr("MID")
tb_mi.Text = datardr("MIDDLE")
tb_app.Text = datardr("APPELLATION")
tb_prefix.Text = datardr("PREFIX")
tb_sex.Text = datardr("SEX")
tb_status.Text = datardr("STATUS")
End If
However, I noticed that it's not displaying all data coming from these fields. I can only view the SURNAME, GIVEN, MID and MIDDLE but the others are not displayed.. I have double checked my database fields and I'm sure that they're the same and without special characters or whitespaces.
Please help. Thanks!
Here is the exact code that I have => VB2010 and MySQL Code
Alright, here's another answer for you.
I think it's because of your SQL statement in line 21.
I assume you are selecting ONE record (am I right?), so that you can insert the resultant fields into the text boxes. And, you order the result with SURNAME.
Did you double check whether there are already data inside the masterlist table? Especially check, if you already entered the data in every field in every row.
In line 30, you called datardr.Read() method, so the DataReader object datardr will read the first record line it encountered in the result of the sql statement.I think only the four fields of the first record, SURNAME, GIVEN, MID and MIDDLE has data values, and any other fields contain null values. So, you only got these FOUR values appeared inside the text boxes, and any other fields appeared to be blank.
I THINK IT MIGHT BE THE MAIN PROBLEM. Just check whether the data you wanted to be appeared already existed in the database table. OK!
And another suggestion. Don't you think you might need WHERE clause in your SQL statement? Well, you want to display only one record, don't you?
WISH YOU BEST LUCK!!! :-)
I think you better check the sql statement that passed into the command object, cmd.
Maybe you didn't select the entire record with select *.
And, one more recommendation.
If datardr is the DataReader, I highly recommend you NOT to use it. It cause much problems than it serves.
The more flexible approach is to use just the DataTable.
The command object has ExecuteNonQuery method that returns the DataTable object.
It is more flexible and much more easier to use than DataReader. Trust Me...! ;-)
This is the kind of thing I feel I should already know, but don't...
In MS Access, if a query consists of n calculated fields (say calc_1, calc_2, .... calc_n) but I only want to use a subset of them in a particular form or report - say calc_x, calc_y and calc_z - would Access calculate all n calculations when running SELECT calc_x, calc_y, calc_z FROM myquery and then return the ones I want, or would it be smart enough to only calculate calc_x, calc_y and calc_z?
In my case I'm using Access 2003 but presumably the answer is the same for all versions.
Access is smart and don't calculate not-visible fields.
Tried with Access 2003
Like #David, I did not believe #Andreas's answer at first. So I tested it myself as follows. I created the following function:
Function Watch(Val, Optional CalledFrom As String = "")
Debug.Print Val, CalledFrom
Watch = Val
End Function
Then I created a table named "Dummy" with a single field named "ID". I created a form and used the following as the form's RecordSource:
SELECT Watch([ID],"ShowInForm") AS ShowInForm,
Watch([ID],"HideFromForm") AS HideFromForm
FROM Dummy;
I added a single textbox control with a ControlSource of ShowInForm.
I then opened the form and got this in the immediate window:
1 ShowInForm
1 ShowInForm
1 ShowInForm
I then went back to the RecordSource and previewed it in Datasheet view and got this:
1 ShowInForm
1 HideFromForm
I'm not sure why the "ShowInForm" expression is evaluated three times in the form, but it seems pretty clear that the unused field, "HideFromForm", does not get evaluated.
To address #HansUp's comment, I went back and saved a query named "Qry":
SELECT Watch([ID],"ShowInForm") AS ShowInForm,
Watch([ID],"HideFromForm") AS HideFromForm
FROM Dummy;
Then changed the form RecordSource to:
Select ShowInForm FROM Qry
This produced the same result as before when I opened the form (ie, 3 lines of 1 ShowInForm). Interestingly, when I opened the RecordSource in datasheet view I got this:
1 ShowInForm
1 ShowInForm
In other words, it evaluated the ShowInForm field twice. Presumably, once in "Qry" and again in the RecordSource query.
The end result is still a confirmation of #Andreas's answer.
If you include the calculated fields in the SELECT clause of your report or form's recordsource, it will calculate them for each row AS IT IS RETRIEVED.
If you leave them out of the SELECT and include the calculations only in the ControlSource properties of controls on your report/form, then what you say is true.
Also, if you do any sorting/grouping on the calculations or put criteria on them, all rows will be calculated.
Thus, in this recordsource:
SELECT Field1/Field2 As Ratio1, Field3/Field4 As Ratio2, FIeld1, Field2, Field3, Field4
FROM MyTable;
...for each row that is retrieved, both calculations will be executed regardless of whether or not the result is used in the form or report.
If you want to delay calculations to the last possible moment, do NOT include them in the SQL recordsource, but just use them as the ControlSources of the controls that are displaying the calculations. However, this has the downside that you'll see the calculations painting onscreen in many cases.
EDIT:
It seems this may not be correct, but I feel there's something going on here that is not completely explained by #mwolfe02's answer. I'll just leave this here for further discussion.
I put calculations like this on the server side.. computed columns are awesome.
I think that Access finally got this feature in 2007, I don't know how people ever survived without it.