Is there a way to use variables in vba to identify MS-Access report fields? - vba

I am not a programmer, but have been tasked with doing this anyway! We are working on a research project that involves testing properties of different samples. I am trying to create a form that will generate a custom report based on what the user chooses. So, I have multiple text boxes and check boxes to allow the user to define the query parameters (e.g. composition of the sample must contain at least 5% component A) and choose what data they are interested in seeing in said report (e.g. show pH, color, but not melting point). I have successfully created code to generate the query, then generate a report based on that query, but the report defaults to column widths that are generally too big (for example, the pH column width is 3 inches, it only needs to be about 1). I would like to be able to fix this, but have not been able to figure out how. At the same time, some of these fields contain numbers that are averages of multiple test results, so I would like to limit the number of digits shown, and display them as % where appropriate. I started with just fixing the column width issue:
I have tried to make a collection of the fields that are included, then loop through the collection and set column widths, but cannot figure out how to identify a field with a variable:
If I know the field name I can do this:
Reports("ReportName")!FieldID.Width = 200
But if I have a collection of names, FieldNames, or a string VariableName, none of these work, giving me an error that FieldNames or VariableName is not a valid field in the report:
Reports("ReportName")!FieldNames(1).Width = 200
Reports("ReportName")![FieldNames(1)].Width = 200
Reports("ReportName")![VariableName].Width = 200
Is there a way to reference a field name with a variable?
Alternatively, I thought there might be a way to loop through all fields and set widths - this would involve looking up a column width for each field, which I thought to do by adding a key to a collection of column widths. But I cannot find a way to do that, something like:
For each Field in Reports("Report")
Field.Width = ColumnWidthCollection(Field)
Next
This hangs up on the Field.Width line, with "invalid procedure call or argument", which brings me back to how to reference a field name with a variable.
Any help would be greatly appreciated!

Try with:
Reports("ReportName")(VariableName).Width = 200

Related

Adding multiple columns from a pandas data frame into a new column

I ran some code which resulted in either a 1 if something happened or a 0 if it did not. The results are stored in 8 separate columns (count600, count800, etc) which visual studio has as a list type. I then added the 8 columns together and have the results appear in a new column titled SUM_OVER90th. The value stored in the SUM_OVER90th appears like 11111.0 instead of the value 5. I tried a few different scripts which all seem to give a similar result. I'm not sure why I'm not able to add these column together. Thanks for any advice on what I might be doing wrong!
COLS_TO_ADD = ['600_COUNT','800_COUNT','1000_COUNT','1200_COUNT','1400_COUNT','1600_COUNT','1800_COUNT','2000_COUNT']
Q_ETL_sub['SUM_OVER90th'] = Q_ETL_sub[COLS_TO_ADD].sum(axis=1)
enter image description here
One possible reason is that your columns to add are strings, not numbers. You can verify this with
Q_ETL_sub.dtypes
and if they are not numbers, try convert them into integer with
Q_ETL_sub[COLS_TO_ADD] = Q_ETL_sub[COLS_TO_ADD].astype(int)

SSRS: How To Create Dynamic Report With Multiple Subreports?

I am still fairly new to SSRS, and I do not know what I need to/can provide as examples to help clarify my issue.
I am developing an SSRS report that accesses a NAV database and generates a report for an equipment number. My task is to generate a master report that can print multiple of those kind of reports(currently 10 max). I am using sub-reports to get the content that I need for an equipment number.
I am looking for a way to make this dynamic, where I can generate 1 to n sub-reports based on how many values were picked for the multi-value parameter. The end result should be one PDF file that contains the full report for each equipment number listed. I am trying to only use SSRS.
I have seen where I could hide sub-reports then make them visible if a condition is met, but this isn't the functionality that I am looking to use. So, what would be the best way to dynamically generate sub-reports based on a multi-value parameter?
I figured it out. I made the sub-report parameter equal no value. I made the main report with a parameter that can select multiple equipment numbers, a list, and a data set which filtered down to the appropriate equipment numbers to avoid duplication. I made the sub-report object in the main take in the cell value from the list equipment number. When the list proceeded to the next row, it copied all of the objects in the box area.

How can I incorporate entitlements with over 50,000 data points in SSRS Report?

In my SSRS report I am attempting to incorporate entitlements. If a user puts a specific person ID in the parameter, I'd like to be able to compare it against the up to 50,000 ids they are entitled to use and to put up an error message if not.
The available values feature only allows me to use a dropdown, which is incovenient for so many ids. What are my options?
A drop down would be very inconvenient for that many choices. Is it possible to break them down by a category or something like that? You could then create cascading parameters to make the list easier to deal with.
Otherwise it would have to be a free text field. Depending on the complexity of the report contents you could handle it a couple of ways.
If it is a very simple report with just a tablix you can set the no data row value to your error message.
If it is more complex you can display the error message using two rectangles. The first one would simply contain a text box with the error message in it. Then put the actual report comments in the second box. Control the visibility of these rectangles based on an expression that checks the number of rows returned by the dataset or some other indication that the input was invalid. You may even need to create a second dataset to check for input validity if there isn't a reliable way to use your normal query.

access report from dynamic crosstab query and vba to "manually" generate reports

I have come across the problem of generating complex access reports (by complex I mean with data processing, variable number of fields, among others).
Let me explain in deeper detail some of the things I need to implement:
Some fields should not show according to some values in a query
If a certain record does not exist, a nice colored (very noticeable) message should appear instead of the values that would be there (Suppose, for example, that a record with 03/04/2009 in the date field exists, a record with 03/06/2009 in the date field also exists but no record with 03/05/2009 exists. Before showing the data related to the last record, I should print something like "Didn't show up on 03/05/2009")
A bar chart that takes as data not the values in the records, but instead something else that is calculated over a set of records (like an average of all grades for a certain date). The number of series in this chart also varies according to values in the records, this chart would not be in the detail section, but instead in the page heading or some kind of group heading.
It should also be mentioned that the query is a TRANSFORM query (more precisely, an INNER JOIN of many TRANSFORM queries), and thus the number of columns returned by the query varies. While in the past I've been unable to bind this query as the recordsource for the report, somehow Access stopped complaining for now (can someone please clarify this? Is this normal, should I not worry about it and use it as a recordsource or should I avoid it?)
There are two options to achieve what I want (that I can see for now):
Create a report with no record source and lots of unbound fields, and through several events (Report_Open, Section_Format, etc.) and with the help of DAO, manually set the values of these fields. Changing the Data Series of the chart is also possible through VBA.
Set the record source to the query, and create some crazy and confusing VBA code to deal with the data and implement everything I need.
It seems to me that option 2 is going to be a huge headache and waste of time, and I recognize option 1 is pretty much like writing to an Excel file (since all the data is obtained with DAO), which would be much easier since I have much more control over almost everything there (but for many other reasons, we want everything in an access report)
While I'm biased and intend to go with option 1, I have found several problems with this option, for example:
I can't find a way to create new pages in the report with VBA, and thus I'm limited only to the first page.
Lack of some kind of free, online, decent and complete documentation on VBA and Access Reports
Also, if option 2 is more viable, I'm certainly willing to go with it, but I would also need some advice, and perhaps some tips to solving the problems I mentioned in this question.
So, the questions are:
Where can I find some decent and complete documentation on Access Reports and VBA?
How can I create pages in an access report, and choose which page I want to write to?
With the problem I have in my hands, will I reach any bottlenecks I should know about? Should I already be thinking of alternatives to Access Reports (writing to a spreadsheet, for example?)
Sounds like you want to dynamically create the report and avoid all the dummy text boxes.
In regard to:
I can't find a way to create new pages
in the report with VBA, and thus I'm
limited only to the first page.
Your solution #1 seems to assume an unbound report.
I think what I'd do is have the form the crosstab as the rowsource, so you'd have records to generate the pages, and then define your report's controls with no ControlSource (except for the controls that are bound to fields that are always present in the CrossTab). Then you could assign the ControlSources at runtime based on the particular columns. Here's the SQL for a crosstab grabbed from an app I'm working on now:
TRANSFORM First(impNoMatch.PersonID) AS FirstOfPersonID
SELECT impNoMatch.LastName, impNoMatch.FirstBame
FROM impNoMatch
GROUP BY impNoMatch.LastName, impNoMatch.FirstName
PIVOT impNoMatch.Status;
Now, you know that the fields in the SELECT clause will always be present, so if you opened a recordset on the SQL string you are using and count the number of fields in the recordset's Fields collection (you can't use the report's Recordset unless it's an ADO recordset, i.e., not bound to the Recordsource):
Dim strSQL As String
Dim rsFields As DAO.Recordset
Dim lngFieldCount As Long
strSQL = Me.Recordsource
Set rsFields = CurrentDB.OpenRecordset(strSQL)
lngFieldCount = rsFields.Fields.Count
From that, since you know the number of fields in the SELECT statement (i.e., the row headings), you can calculate the number of dynamic controls you want to assign, and you can use this recordset's fields collection to assign the ControlSources and unhide the controls.
You'd start out with all your controls that will display the dynamic fields set so their Visible property is FALSE. You'd also use a naming convention for those controls. In the code below, I've used txtNN, where NN is the numeric index in the Fields collection formatted as 2 digits. Here's the code (which adds lines to what's listed above, and is run in the OnOpen event):
Dim strSQL As String
Dim rsFields As DAO.Recordset
Dim lngFieldCount As Long
Dim l As Long
Dim strControlName As String
strSQL = Me.RecordSource
Set rsFields = CurrentDb.OpenRecordset(strSQL)
lngFieldCount = rsFields.Fields.Count
For l = 2 To lngFieldCount - 1
strControlName = "txt" & Format(l, "00")
Me(strControlName).ControlSource = rsFields.Fields(l).Name
Me(strControlName).Visible = True
Next l
rsFields.Close
Set rsFields = Nothing
Now, if you want to get fancy, you can reformat the controls, changing widths and horizontal/vertical position. If you do that, you have to do it in a different event, and it's a bit tricky to choose that. The only good place to put it is in a report group's header's OnFormat event. If you don't have any grouping, you can add one that doesn't do anything. In the case of my crosstab, a two-level sort on Lastname and Firstname and a header on the Firstname group with nothing in it is a good place to use the OnFormat event to change the appearance/layout of the controls on your report.
As to your question about how to learn how to do this, I recommend picking up an intermediate/advance Access programming book. The Access Developers Handbook is the gold standard on this, and includes tons of examples of programmatic control of reports.

SSRS - Producing a report that is not dynamic in size

I want to build a report that is completely static in size and shape. I'm attempting to mimic a hand-entered report that someone in my organization has been building from a word doc for years.
The critical piece appears to be fixing the number of rows that are produced in the various Table grids that fill the page. I would like them to always contain a set number of rows, whether data is present or not. It would seem that if I can just fix the size my tables, then all the other elements will not be forced to move because of stretching repeater sections.
All my grids are backed by stored procedures, so I'm open to SQL tricks as well.
Sorry i did miss-read the question.
If you know how many rows you need to return (say 20) maybe you could pad some bogus info into your records returned from the stored procedure. You might be able to count the records your query has returned before you send them back, and if you have less than 20 add some bogus ones to the record set, put something like 'NonDisp' or something in them.
Then in the report put an iif statement into the cells that checks for this bogus info, if it is found change the cell to display nothing, otherwise show the valid values
Not a direct answer, but perhaps a workaround you might consider: perhaps you can insert a page break after the table grids that have dynamic sizes, so that all elements that follow it have a fixed position (relative to the top of the page).
Add a parent group to tablix with =Ceiling((RowNumber(Nothing)) / 10000) expression. (10000 or whatever is required no. of rows)
In page break properties of group, check box for insert break between groups, leave the bottom boxes un-checked.
Optionally, we may chose to set hidden property true for text boxes added because of new parent group.
In tablix properties, check box for "Keep together on one page".