I honestly don't think this is possible but I wanted to at least try. Everyday I have a report that is generated daily and sent out via SSRS email subscription to various people based on the transactions that I do in a proprietary program. Some days there are actually no transactions so it sends a blank excel file. I dont think it's supported natively so is there so way to hackily add the message "There were no transactions today" in the body of the email if there is no data in the excel file? and on days there is say something like "Transactions in attached Excel file"
So can someone please confirm. Is this possible? Or no?
Actually, this is natively possible and it is awesome! What you're looking for is a data driven subscription. You create one by going to the subscription tab under the management page for the report. There are two options: Create Subscription and Create Data-Driven Subscription. Click on the Create Data-Driven Subscription.
I apologize for the length from here but there is just so much to say about these!
I can't elaborate on the steps for everything here because it can be as in-depth a process to set up as you want it to be; there are a ton of options! Here's the MSDN article on Data-driven subscriptions, but you'll find it minimally helpful. Here's the TechNet Tutorial on how to create one, but I think you'll find that it doesn't delve as deep as you might like to go. I just learned everything by trial and error.
There's oh so much to say about these, but essentially you write a SQL query that evaluates something in your data and, as a result, gives the subscription different values for different variables, such as "Comments" (the body of the email written in html), "Include Report" (true/false), and "Render Format" to name a few.
It's important to note that for each line your query returns, one email will be sent. So if you wanted to send out three transaction report emails, you would want to make sure your query returns three rows with all the appropriate data.
For your own edification, here's a redacted copy of one of my queries that drives a report. You'll notice the comment field is quite long as it needs to be written in html. But SQL can handle the very long strings so long as you can formulate them correctly.
So, in your case, you would want to make Include_Report false when there are no transactions and then change the comment to a proper message about why no report is attached.
The purpose of this query is to look for server issues and if issues are found, send out an email (without the report attached) that tells end users it will be coming later. (I'm not in charge of the server performance and the people that are frequently don't fix it in time).
You'll notice that I have a field for every input variable into the SSRS subscription. This way, I can control how the report is emailed based on any script I can dream up. It also makes setup a little easier. I've also built in a quick way to test the subscription so I can play with it without it going to End Users and changing it to go out to end users takes seconds.
/*********************************************************/
/* Change #Testing to 'TEST' to have all emails */
/* sent to Christopher Brown */
/*********************************************************/
/* Change #Testing to 'PROD' to have all emails */
/* sent to normal recipients. */
/*********************************************************/
Declare #Testing varchar(4) = 'TEST';
With Problems as (
/*Script that looks for hardware failures or anything that would
cripple the accuracy of the report.*/
)
Select Case
When #Testing = 'TEST'
Then 'Just.Me#work.com'
When #Testing = 'PROD'
Then 'End.Users#work.com'
Else 'Just.Me#work.com'
End as 'To'
, Case
When #Testing = 'TEST'
Then 'Just.Me#work.com'
When #Testing = 'PROD'
Then 'IT.Group#work.com'
Else 'Just.Me#work.com'
End as 'CC'
, '' as 'BCC'
, 'Just.Me#work.com' as 'Reply-To'
, Case
When #Testing = 'TEST'
Then '***TEST***'
Else ''
End +
Case
When /*Problems Indicated*/
Then '#ReportName - Report Delayed'
Else '#ReportName for ' + CONVERT(varchar(10),getdate(),101)
End as 'Subject'
, 'Normal' as 'Priority'
, Case
When /*Problems Indicated*/
Then 'False'
Else 'True'
End as 'Include_Report'
, 'PDF' as 'Render_Format'
, Case
When /*Problems Indicated*/
Then 'High'
Else 'Normal'
End as Priority
, 'false' as 'Include_Link'
, Case
When /*Problems Indicated*/
Then '<html><Body><Font Face="Constantia","Times New Roman"><p>This Report could not be created at this time. We will send out an updated Report once the server issues have been resolved. If you have questions, please contact us.</p></Font></body></html>'
Else '<html><Body><Font Face="Constantia","Times New Roman"><p>Attached is the Report. When the report is run on a Monday, it does one thing.</p><p>Every other weekday, the report does something slightly different. Please note that the report is scheduled to run every weekday, Monday through Friday, regardless of holiday schedules.</p><p>If you have questions about the report, please contact us.</p><p>If the attached report is empty or missing vital information, click here to notify us.</p></Font></body></html>'
End as 'Comment'
From Problems
Related
We have a few thousand companies in Exact Online from which a certain percentage runs their own accounting and has their own license. However, there is a daily changing group of companies that are behind with their payments to Exact and therefore their companies are blocked.
For all companies we run Invantive Data Replicator to replicate all Exact Online companies into a SQL Server datawarehouse for analytical reporting and continuous monitoring.
In the SystemDivisions table, the state of such a blocked company remains at 1 (Active). It does not change to 2 (Archive) or 0 (upcoming). Nor is there any enddate set in the past.
However, when the XML or REST APIs are used through a query from Invantive SQL or directly from Python on such a blocked company there are lot of fuzzy error messages.
Currently we have to open each company which had an error during replication individually each day and check whether a block by Exact is causing the error and for what reason.
It seems that there is no way to retrieve the list of blocked companies.
Is there an alternative?
Although it is not supported and disadviced, you can access a limited number of screens in Exact Online using native requests. It is rumoured that this is not possible for all screens.
However, you are lucky. The blocking status of a company can be requested using the following queries:
insert into NativePlatformScalarRequests(url, orig_system_group)
select /*+ ods(false) */ 'https://start.exactonline.nl/docs/SysAccessBlocked.aspx?_Division_=' || code
, 'BLOCK-DIV-CHECK-' || code
from systemdivisions
create or replace table currentlyblockeddivisions#inmemorystorage
as
select blockingstatus
, divisioncode
from ( select regexp_replace(result, '.*<table class="WizardSectionHeader" style="width:100%;"><tr><th colspan="2">([^<]*)</th>.*', '$1', 1, 0, 'n') blockingstatus
, replace(orig_system_group, 'BLOCK-DIV-CHECK-', '') divisioncode
from NativePlatformScalarRequests
where orig_system_group like 'BLOCK-DIV-CHECK-%'
)
where blockingstatus not like '%: Onbekend%'
Please note that the hyperlink with '.nl' needs to be replaced when you run on a different country. The same holds for searching on the Dutch term 'Onbekend' ('Unknown' in english).
This query runs several thousand of HTTP request, each requesting the screen with the blocking status of a company. However, when the company is not blocked, the screen reports back a reason of 'Unknown'.
These companies with 'Unknown' reason are probably not blocked. The rest is.
We have dozens of data driven subscriptions that we run manually at the beginning of the month that use file share delivery. They point to a certain server's shared drive.
That server is going away, so we need to either manually change the data driven sql that dynamically creates a path/filename for the dozens of subscriptions,
or we were hoping we could run an update statement or something? Below is kind of what we want to change. All instances of ATLACT02 to something else.
!!!!!!!!!!
Select 'Pro Bono Section ' + RTRIM(SECT_CODE) + ' ' + RTRIM(#PERIOD) AS 'FILE_NAME',
'\ATLACT02\Crystal Reports\Reports\Section\'+RTRIM(SECT_CODE) +'\'+ RTRIM(#PERIOD) AS 'PATH',
RTRIM(SECT_CODE) AS SECT,
RTRIM(#PERIODEND) AS PERIODEND,
RTRIM(#PERIODBEGIN) AS PERIODBEGIN
From _HBL_SECT SECT
Where SECT.INACTIVE = 'N' AND (SECT_CODE BETWEEN '100' AND '699')
AND SECT_CODE NOT IN ('101','201','301','401','501','601')
in your reporting services database
select * from Subscriptions where ExtensionSettings like '%ATLACT02%'
You can use some fancy TSQL to update the XML in that field or simply use the REPLACE
UPDATE Subscription
SET ExtensionSettings = REPLACE(ExtensionSettings,'ATLACT02','NewServerName')
WHERE ExtensionSettings like '%ATLACT02%'
Obviously a bit of testing would be pretty useful before attempting to change all your datadriven subscriptions
I'm designing a database to track requests. Currently, I have a form that its' record source is based off a query "Unassigned Requests". This query is based off my table Requests, and returns all "unassigned Requests". In this form, I would like the status field to change to "Assigned", once a Tech field has been assigned to the request. I currently have the Default for the Tech Assigned field set to "Blank', and the status field set to 'Unassigned". Both of these fields are combo boxes. The status field has a control source from the request table and row source from the status table. The tech assigned field has a control source from the Tech table and the row source is based off a query.
I have tried multiple solutions that have not seemed to work. I have limited experience with Macros and VBA. I would appreciate any suggestions on solving this problem.
I am going to make some assumptions regarding your post and if any are incorrect please let me know.
You have a request form where a request is assigned to a Tech. On that form there is a dropdown for the status, and also for the Tech.
You want to make it so when the tech dropdown is filled out with a tech's name you want the dropdown to change to assigned.
If this is the case I would recommend using the Tech Assigned field's AfterUpdate event. The code would look something like this:
Private Sub cboTech_Assigned_AfterUpdate()
If Nz(Me.cboTech_Assigned.Value, "") <> "" Then
Me.cboStatus = "Assigned"
Else
Me.cboStatus = ""
End If
End Sub
Obviously you will need to adjust to your own naming scheme. I should also point out that I don't even know if that Nz function is needed, I have just gotten into the habit of putting it everywhere. If I misunderstood something about what you want to do please let me know!
I found the following in the "e-mail" field of my newsletter subscriber database: ' OR 1=1/*
I know it's a SQL injection, but that's it. I've googled it a little bit, but I'm still on clear on what exactly it's trying to achieve. This occurred early Nov, and to my knowledge we had no outages around that time. Can any of you kind souls tell me what this guy was probably trying and do? Is there any way to know whether he achieved what he was trying to do?
I know virtually nothing about this and I'm worried. :(
'OR 1=1 is an attempt to make a query succeed no matter what
The /* is an attempt to start a multiline comment so the rest of the query is ignored.
An example would be
SELECT userid
FROM users
WHERE username = ''OR 1=1/*'
AND password = ''
AND domain = ''
As you can see if you were to populate the username field without escaping the ' no matter what credentials the user passes in the query would return all userids in the system likely granting access to the attacker (possibly admin access if admin is your first user). You will also notice the remainder of the query would be commented out because of the /* including the real '.
The fact that you can see the value in your database means that it was escaped and that particular attack did not succeed. However, you should investigate if any other attempts were made.
It probably aimed to select all the informations in your table. If you use this kind of query (for example in PHP) :
mysql_query("SELECT * FROM newsletter WHERE email = '$email'");
The email ' OR 1=1/* will give this kind of query :
mysql_query("SELECT * FROM newsletter WHERE email = '' OR 1=1/*");
So it selects all the rows (because 1=1 is always true and the rest of the query is 'commented'). But it was not successful
if strings used in your queries are escaped
if you don't display all the queries results on a page...
The specific value in your database isn't what you should be focusing on. This is likely the result of an attacker fuzzing your system to see if it is vulnerable to a set of standard attacks, instead of a targeted attack exploiting a known vulnerability.
You should instead focus on ensuring that your application is secure against these types of attacks; OWASP is a good resource for this.
If you're using parameterized queries to access the database, then you're secure against Sql injection, unless you're using dynamic Sql in the backend as well.
If you're not doing this, you're vulnerable and you should resolve this immediately.
Also, you should consider performing some sort of validation of e-mail addresses.
Its better if you use validation code to the users input for making it restricted to use symbols and part of code in your input form. If you embeed php in html code your php code have to become on the top to make sure that it is not ignored as comment if a hacker edit the page and add /* in your html code
Creating a simple UI using MS Access, hoping to do minimal actual coding (actually helping a friend who is not a coder).
Simplified requirement: Single table, primary key is phone number, lots of other non-mandatory fields. Display a form allowing just the phone number to be entered, if a record with that key exists display the full record, if a record with that key does not exist bring up an form allowing the other fields to be entered for this phone number and hence create a new record.
Q1: Any simple way to achieve this kind of function? Example?
We've got some of this going with a standard form, can execute code if insertion fails, but a standard dialogue box is displayed warning about the duplciate key violation.
Q2: How can we trap that attempted insertion, avoid having the dialogue come up?
You will have to get your hands dirty and write some code to get this outcome. A starting point would be something like this presto code. Post back if you get stuck on any of the parts.
If fCheckIfRecordExists(lYourKey)=True then
Docmd.OpenForm “frmEditExistingRecord”
Else
Docmd.OpenForm “frmEnterNewRecord”
End if
Public function fCheckIfRecordExists (lYourKey as Long) as Boolean
‘Code to check if a record exists, simple method is to use dLookup or a count SQL statement with the criteria as the key you are trying to find
End function
EDIT:
First things first make a form with 1 text box called txtPhone_number and a command button called cmdSearch.
Next put this bit of code in the module behind the form
Public Function fDoes_record_exist(strPhone_number As String) As Boolean
If DCount("Phone_number", "tblYour_table", "Phone_number=" & strPhone_number) > 0 Then
fDoes_record_exist = True
Else
fDoes_record_exist = False
End If
End Function
Next you need to put some code behind the click event of the command button. This code can be expanded on to check for a valid phone number later if you want
If fDoes_record_exist(Me.txtPhone_number) = True Then
DoCmd.OpenForm "frmShow_existing_record"
Else
DoCmd.OpenForm "frmEnter_new_record"
End If
That should set you on your way nicely but post back if you run into problems
Here is an overview of the process with Access logic:
You need an unboud control labelled Phone in the form header, where user will be able to enter the phone number to search. You need to use the After_Update event of that control to trigger your search. There will be a second Phone control, bound this time, in the Detail section of the form for effective data entry/update.
Use the Form_Error event to intercept the error message when user tries to save a duplicate key, in order to display a nice message, and eventually Cancel his changes.
The advice from Kevin Ross to use VB Code is clearly one approach, and I think is appropropriate if we anticipate less trivial requirements in future. However I'm in a situation where I'm helping someone with zero coding background and hence if possible I'd prefer to let them use simple Macros rather than full-scale VB.
As it happens the functionality I require can be implemented with just Macros, and it depends on the suggestion from iDevelop.
The outline of the solution I used:
Create an InitialEntry form with no association to any particular table, it has:
a data entry field for the telephone number
a read-only text box where I can display a message
a button labelled Add
a button labelled Show
I write three macros:
A macro AlreadyExists that displays a message saying "We already that one"
A macro NewEntry that opens a data entry form for my table, in Add mode, and which copies the phone number from InitialEntry!TelephoneNumber
A macro TestForExisting this uses a condition
DCount("*","MyTable","[PhoneNumber] = [FormPhoneNumber] " ) > 0
to control whether to execute AlreadyExists, and a similar test to control whether to call NewEntry.
While this is not as efficient as VB, it does seem to be understandable by a non-coder, so at least we can implement our application.