Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 911
  • Last Modified:

Send an RTF as Read Only

I have a report that I send via email in rtf format. Is there any way to make the file read only so that the recipient can't modify the document?
0
shanej
Asked:
shanej
  • 6
  • 3
  • 2
  • +1
3 Solutions
 
Jeffrey CoachmanCommented:
shanej,

No

In order to create a Read-Only Document, you can use the "SnapShot" format or save the Report as a PDF.

There are tons of free utilities to convert your report to PDF's.
here are two:
http://www.cutepdf.com/
http://www.lebans.com/reporttopdf.htm

If you want to use the Snapshot then you must ensure that each recipient has the viewer, that is why PDF is preferred.

JeffCoachman
0
 
shanejAuthor Commented:
Okay, thanks.  But how do I attach the PDF file you describe using SendObject?
0
 
irudykCommented:
You could attempt to output the report as an RTF, then use code to open the RTF document and resave it as a protected form (thus making it read-only) and then create a new email with the RTF file added as an attachment.  The code below could be modified to meet your specific needs.
Function SendReadOnlyReport()
 
'output report to RTF
DoCmd.OutputTo acOutputReport, "NameOfReport", acFormatRTF, "C:\NameOfReport.rtf"
 
'make RTF read-only
Dim wd As Object
Set wd = CreateObject("Word.Application")
With wd.Application
    .Documents.Open "C:\NameOfReport.rtf"
    .ActiveDocument.Protect 2, True, "EnterPasswordHere"
    .ActiveDocument.Save
    .ActiveDocument.Close
    .Quit
End With
 
'create/display email with RTF attachment
Dim ol As Object
Dim olNameSpace As Object
Dim olMessage As Object
Set ol = CreateObject("Outlook.Application")
Set olNameSpace = ol.GetNamespace("MAPI")
Set olMessage = ol.CreateItem(0)
olMessage.Attachments.Add "C:\NameOfReport.rtf"
olMessage.Display
 
Set olMessage = Nothing
Set olNameSpace = Nothing
Set ol = Nothing
 
End Function

Open in new window

0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
shanejAuthor Commented:
Thanks!  Where do I place the code and how do I call the function?  Should it go behind the button I am using to call the SendObject method?  Here is the code as it appears currently:

Private Sub btnEmail_Click()
On Error GoTo Err_btnEmail_Click

    Dim stDocName As String
   
    stDocName1 = "POEmailReportShipTo"
    stDocName2 = "POEmailReportRemoveFrom"
    stDocName3 = "POEmailReportReleaseTo"
    stDocName4 = "POEmailReportWorkAddress"
   
    On Error Resume Next
       
    Me!POUser = CurrentUser
   
    DoCmd.RunCommand acCmdSaveRecord
   
    If Me!ShipRemoveRelease = "1" Then
        DoCmd.SendObject acReport, stDocName1, acFormatRTF, Me!VendorEmail, , , "NIS Purchase Order"
    End If
    If Me!ShipRemoveRelease = "2" Then
        DoCmd.SendObject acReport, stDocName2, acFormatRTF, Me!VendorEmail, , , "NIS Purchase Order"
    End If
    If Me!ShipRemoveRelease = "3" Then
        DoCmd.SendObject acReport, stDocName3, acFormatRTF, Me!VendorEmail, , , "NIS Purchase Order"
    End If
    If Me!ShipRemoveRelease = "4" Then
        DoCmd.SendObject acReport, stDocName4, acFormatRTF, Me!VendorEmail, , , "NIS Purchase Order"
    End If

Exit_btnEmail_Click:
    Exit Function

Err_btnEmail_Click:
    MsgBox Err.Description
    Resume Exit_btnEmail_Click
   
End Function
0
 
irudykCommented:
Try revising you code as follows:

Private Sub btnEmail_Click()
On Error GoTo Err_btnEmail_Click
 
    Dim stDocName(4) As String
    
    stDocName(1) = "POEmailReportShipTo"
    stDocName(2) = "POEmailReportRemoveFrom"
    stDocName(3) = "POEmailReportReleaseTo"
    stDocName(4) = "POEmailReportWorkAddress"
    
    On Error Resume Next
        
    Me!POUser = CurrentUser
    
    DoCmd.RunCommand acCmdSaveRecord
    
    'output report to RTF
    DoCmd.OutputTo acOutputReport, stDocName(Me!ShipRemoveRelease), acFormatRTF, "C:\" & stDocName(Me!ShipRemoveRelease) & ".rtf"
 
    'make RTF read-only
    Dim wd As Object
    Set wd = CreateObject("Word.Application")
    With wd.Application
        .Documents.Open C:\" & stDocName(Me!ShipRemoveRelease) & ".rtf"
        .ActiveDocument.Protect 2, True, "EnterPasswordHere"
        .ActiveDocument.Save
        .ActiveDocument.Close
        .Quit
    End With
 
    'create/display email with RTF attachment
    Dim ol As Object
    Dim olNameSpace As Object
    Dim olMessage As Object
    Set ol = CreateObject("Outlook.Application")
    Set olNameSpace = ol.GetNamespace("MAPI")
    Set olMessage = ol.CreateItem(0)
    olMessage.To = Me!VendorEmail
    olMessage.Subject = "NIS Purchase Order"
    olMessage.Attachments.Add C:\" & stDocName(Me!ShipRemoveRelease) & ".rtf"
    olMessage.Display
    'or to send (you will likely get an Outlook security prompt appear)
    'olMessage.Send
    Set olMessage = Nothing
    Set olNameSpace = Nothing
    Set ol = Nothing
 
    'delete output file
    Kill C:\" & stDocName(Me!ShipRemoveRelease) & ".rtf"
 
Exit_btnEmail_Click:
    Exit Function
 
Err_btnEmail_Click:
    MsgBox Err.Description
    Resume Exit_btnEmail_Click
    
End Function

Open in new window

0
 
shanejAuthor Commented:
ShipRemoveRelease is an Access 97 frame control.  In my case, there are four options of reports that can be chosen using radio buttons inside the frame control.  Hence the four If, Then statements in my code sample that are used to choose and process the reports.  Am I correct in assuming that your code would be placed in its entirety inside each of my If, Then statements for each of the four possible reports with the lines of your code referencing my reports changed as necessary?
0
 
irudykCommented:
No, I am suggesting that you replace your entire Sub btnEmail_Click() with my version of Sub btnEmail_Click().
I use an array stDocName(4) to store and select the correct report name based upon the value of the ShipRemoveRelease.  So for ShipRemoveRelease values of 1, 2, 3 and 4 the report names would be:
    stDocName(1) = "POEmailReportShipTo"
    stDocName(2) = "POEmailReportRemoveFrom"
    stDocName(3) = "POEmailReportReleaseTo"
    stDocName(4) = "POEmailReportWorkAddress"
Also, I'm using DoCmd.OutputTo and not DoCmd.SendObject which is why I have a section called
     'create/display email with RTF attachment
wherein I've replicated the recipient and subject for the email in additon to the document to be attached.
0
 
shanejAuthor Commented:
Got it.  I will evaluate and let you know ASAP if I have any more questions or clarifications.  I appreciate your time and effort and I promise I'll get back to you.  I am in California, USA and have to hit the hay for an early day tomorrow.  So, I'll say goodnight for now.....

Shane
0
 
shanejAuthor Commented:
Thank you IRUDYK.  The code that actually works is pasted below.  I had to add a " (quote) prior to the C:\ in each line that referenced it.  You'll notice, too, that I had to change the Exit and End statements to reference the Sub and not a function.  These function references were left in there by mistake from previous trials of other code.

I do have one more question, though.  The Dim statement references stDocName(4).  My limited coding ability makes me think it should be a requirement to Dim stDocName(1), (2), and (3) as well.  Why isn't this necessary?



Private Sub btnEmail_Click()
On Error GoTo Err_btnEmail_Click
 
    Dim stDocName(4) As String
   
    stDocName(1) = "POEmailReportShipTo"
    stDocName(2) = "POEmailReportRemoveFrom"
    stDocName(3) = "POEmailReportReleaseTo"
    stDocName(4) = "POEmailReportWorkAddress"
   
    On Error Resume Next
       
    Me!POUser = CurrentUser
   
    DoCmd.RunCommand acCmdSaveRecord
   
    'output report to RTF
    DoCmd.OutputTo acOutputReport, stDocName(Me!ShipRemoveRelease), acFormatRTF, "C:\" & stDocName(Me!ShipRemoveRelease) & ".rtf"
 
    'make RTF read-only
    Dim wd As Object
    Set wd = CreateObject("Word.Application")
    With wd.Application
        .Documents.Open "C:\" & stDocName(Me!ShipRemoveRelease) & ".rtf"
        .ActiveDocument.Protect 2, True, "EnterPasswordHere"
        .ActiveDocument.Save
        .ActiveDocument.Close
        .Quit
    End With
 
    'create/display email with RTF attachment
    Dim ol As Object
    Dim olNameSpace As Object
    Dim olMessage As Object
    Set ol = CreateObject("Outlook.Application")
    Set olNameSpace = ol.GetNamespace("MAPI")
    Set olMessage = ol.CreateItem(0)
    olMessage.To = Me!VendorEmail
    olMessage.Subject = "NIS Purchase Order"
    olMessage.Attachments.Add "C:\" & stDocName(Me!ShipRemoveRelease) & ".rtf"
    olMessage.Display
    'or to send (you will likely get an Outlook security prompt appear)
    'olMessage.Send
    Set olMessage = Nothing
    Set olNameSpace = Nothing
    Set ol = Nothing
 
    'delete output file
    Kill "C:\" & stDocName(Me!ShipRemoveRelease) & ".rtf"
 
Exit_btnEmail_Click:
    Exit Sub

Err_btnEmail_Click:
    MsgBox Err.Description
    Resume Exit_btnEmail_Click
   
End Sub
0
 
dannywarehamCommented:
Not to hijack (do not accept as an answer)

The Dim statement simply tells Access/Jet to reserve a certain amount of memory for a variable.

In the case of an array, Dim stDocName(4) As String, you reserve a piece of memory for string information and declare that the array will have four seperate values.

You don't need to declare Dim stDocName(1) As String etc, as it's aready declared with the Dim stDocName(4) As String statement

Does that help?
0
 
shanejAuthor Commented:
Yeah... I guess I thought that since the other Dim statements are referencing discrete objects, that they would have to be individually "Dim'd."  Does this work because only one object at a time is used during the session, therfore allowing the "blanket Dim'g" of the variables that are available?  Sorry to be so nebulus in my writing, but this stuff is harder than h... for me to describe.
0
 
dannywarehamCommented:
The easiest way to think of it is that a Dim'd variable is a box.
The box can hold different types of things - numbers, letters, dates or a variety.

An array is a Dim'd variable with a number in brackets. This changes the box from a standard cardboard box into more of a chocolate box - with lots of little areas for your chocolates.

You only need to say "Hey Access, this is a box, but it'sgoing to have four chocolate areas in it".

So:

Dim myVariable as String
means "Access - there's a box and I'm gonna keep letters in it"

Whereas:

Dim myVariable (3) as String
means "Access - there's a box and I'm gonna keep letters in it, but there's going to be three little areas in that box"

Does that make sense?
0

Featured Post

What is SQL Server and how does it work?

The purpose of this paper is to provide you background on SQL Server. It’s your self-study guide for learning fundamentals. It includes both the history of SQL and its technical basics. Concepts and definitions will form the solid foundation of your future DBA expertise.

  • 6
  • 3
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now