Highlighted
Absent Member.
Absent Member.
2482 views

Visual COBOL Personal Edition - how to write out a MS-Word document

Jump to solution

I have Vis CBL P/Edit with VS2012 on Win/8.1

All is well but I want to be able to write a file with simple formatting and colours, e.g. a Word doc

I am sure it can be done but I haven't been able to find it in the documentation

Can anyone please point me to the documentation to read for this?

And/or a sample program?

TIA

0 Likes
1 Solution

Accepted Solutions
Highlighted
Micro Focus Expert
Micro Focus Expert

RE: Visual COBOL Personal Edition - how to write out a MS-Word document

Jump to solution

Are you looking to do this in native code or managed code?

MS Word is accessible through a COM class in native code or through an interop class under .NET. Both allow you to create documents programatically.

The following is an example which is provided with Net Express for creating a Word document from a native COBOL application using COM:

      *> This is required for OLE applications
      $set ooctrl(+P)

      ****************************************************************
      * Copyright (C) 1997-1999 Micro Focus International Ltd.
      * All Rights Reserved.
      ****************************************************************
      * The program demonstrates the use of OLE Automation to        *
      * send messages to objects in another application. This        *
      * example uses Microsoft Word.                                 *
      *                                                              *
      * It also demonstrates exception handling with regard to OLE   *
      * objects, and the OLE support timeout method.                 *
      *                                                              *
      * The Word interface is documented in the file vbawrd8.hlp     *
      * shipped with Microsoft Word 97 and vbawrd9.chm shipped       *
      * with Microsoft Word 2000.                                    *
      *                                                              *
      * REQUIREMENTS: Microsoft Word 97 or above needs to be         *
      * installed.                                                   *
      *                                                              *
      * $(#) V1.0                                                    *
      ****************************************************************

       program-id. worddemo.

       class-control.
       *> Native Object COBOL classes
           olesup is class "olesup"           *> OLE support class
       *> OLE automation classes
           wordapp is class "$OLE$word.application"
           .

       working-storage section.
       01 wordServer       object reference value null.
       01 theDocument      object reference value null.
       01 theDocuments     object reference value null.
       01 theSelection     object reference value null.
       01 theFind          object reference value null.
       01 theParagraph     object reference value null.
       01 theParagraphs    object reference value null.
       01 theRange         object reference value null.

       01 found            pic s9(9) comp-5.

       procedure division.
           *> Set the timeout for the OLE "busy" error to 100ms
           *> Using this method is recommended for Word applications
           invoke olesup "setOLEBusyTimeout" using by value 100

           *> Create an instance of Word
           invoke wordapp "new" returning wordServer

           *> Make it visible
           invoke wordServer "SetVisible" using by value 1

           *> Get the Word documents collection object
           invoke wordServer "getDocuments" returning theDocuments

           *> Create a new document. The Template and NewTemplate
           *> parameters for this method are optional
           invoke theDocuments "add"

           *> We no longer need the Documents collection
           invoke theDocuments "finalize" returning theDocuments

           *> Get the current selection
           invoke wordServer "getSelection" returning theSelection

           *> Insert some lines of text in the new document
           invoke theSelection "InsertAfter" using
                                      "This is a test line" & x"0d"
           invoke theSelection "InsertAfter" using
                                     "This is the third line" & x"0d"

           *> Finished with the selection object
           invoke theSelection "finalize" returning theSelection

           *> Oops - we've put "third" instead of "second"
           *> So, we'll replace that word. This is a bit convoluted,
           *> but it's intended to give an idea of how collections work

           *> Get the active document
           invoke wordServer "getActiveDocument" returning theDocument

           *> Get the Paragraphs collection, then the second paragraph
           *> using the item method, then the range of that paragraph;
           *> Once we have the range, we've finished with paragraphs!
           *> This does *exactly* the same as the VB command
           *>   Range = Document.Paragraphs(2).Range
           invoke theDocument "getParagraphs" returning theParagraphs
           invoke theParagraphs "item" using by value 2
                               returning theParagraph
           invoke theParagraph "getRange" returning theRange
           invoke theParagraph "finalize" returning theParagraph
           invoke theParagraphs "finalize" returning theParagraphs

           *> Get the Find object and ask it to find the text "third"
           *> This should change theRange object's character range
           invoke theRange "getFind" returning theFind
           invoke theFind "setForward" using by value 1
           invoke theFind "setText" using by content z"third"
           invoke theFind "execute"
           invoke theFind "getFound" returning found
           invoke theFind "finalize" returning theFind

           if found not = 0
               *> Select our new range of characters
               invoke theRange "select"

               *> Finally, change the word to the correct word!
               invoke theRange "setText" using "second"
           end-if
           invoke theRange "finalize" returning theRange

           *> Print the document out
           invoke theDocument "PrintOut" using by value 0

           *> Close it without saving it
           invoke theDocument "Close" using by value 0

           *> We've finished with the document object
           invoke theDocument "finalize" returning theDocument

           *> Tell Word to quit (it won't shut down otherwise)
           invoke wordServer "quit"

           *> We've now finished with the Word object
           invoke wordServer "finalize" returning wordServer

           exit program
           stop run.



The following is a managed code .NET application that uses the Interop class:

      $set ilusing"System.Windows.Forms"
      $set ilusing"Microsoft.Office.Interop.Word" 
       program-id. Program1 as "testnetword.Program1".
       data division.
       working-storage section.
       01 winword type Microsoft.Office.Interop.Word.Application.
       01 document type Document.
       01 headerRange type Range.
       01 footerRange type Range.
       01 para1 type Paragraph.
       01 para2 type Paragraph.
       01 firstTable type Table.
       01 myHeaderFooter type WdHeaderFooterIndex value type WdHeaderFooterIndex::wdHeaderFooterPrimary.
       procedure division.
 
           try
              *>Create an instance for word app
              set winword to new Microsoft.Office.Interop.Word.Application
              *>Set status for word application is to be visible or not.
              set winword::Visible to false
              *>Create a missing variable for missing value
              declare missing as object = type System.Reflection.Missing::Value
              *>Create a new document
              set document to winword::Documents::Add(by reference missing, by reference missing, by reference missing, by reference missing)
              *>Add header into the document
              perform varying mysection as type Section thru document::Sections
                 *>Get the header range and add the header details.
                 set headerRange to mysection::Headers[myHeaderFooter]::Range
                 invoke headerRange::Fields::Add(headerRange, type WdFieldType::wdFieldPage as object, by reference missing, by reference missing)
                 set headerRange::ParagraphFormat::Alignment to type WdParagraphAlignment::wdAlignParagraphCenter
                 set headerRange::Font::ColorIndex to type WdColorIndex::wdBlue
                 set headerRange::Font::Size to 10
                 set headerRange::Text to "Header text goes here"
              end-perform

              *>Add the footers into the document
              perform varying wordSection as type Section thru document::Sections
                 *>Get the footer range and add the footer details.
                 set footerRange to wordSection::Footers[myHeaderFooter]::Range
                 set footerRange::Font::ColorIndex to type WdColorIndex::wdDarkRed
                 set footerRange::Font::Size to 10
                 set footerRange::ParagraphFormat::Alignment to type WdParagraphAlignment::wdAlignParagraphCenter
                 set footerRange::Text to "Footer text goes here"
              end-perform
  
              *>adding text to document
              invoke document::Content::SetRange(0, 0)
              set document::Content::Text to "This is test document " & type Environment::NewLine
  
              *>Add paragraph with Heading 1 style
              set para1 to document::Content::Paragraphs::Add(by reference missing)
              declare styleHeading1 as object = "Heading 1"
              invoke para1::Range::set_Style(by reference styleHeading1)
              set para1::Range::Text to "Para 1 text"
              invoke para1::Range::InsertParagraphAfter

              *>Add paragraph with Heading 2 style
              set para2 to document::Content::Paragraphs::Add(by reference missing)
              declare styleHeading2 as object = "Heading 2"
              invoke para2::Range::set_Style(by reference styleHeading2)
              set para2::Range::Text to "Para 2 text"
              invoke para2::Range::InsertParagraphAfter

              *>Create a 5X5 table and insert some dummy record
              set firstTable to document::Tables::Add(para1::Range, 5, 5, by reference missing, by reference missing)
              set firstTable::Borders::Enable to 1
              perform varying row as type Row thru firstTable::Rows
                 perform varying cell as type Cell thru row::Cells
                    *>Header row
                    if cell::RowIndex = 1
                       set cell::Range::Text to "Column " & cell::ColumnIndex::ToString
                       set cell::Range::Font::Bold to 1
                       *>other format properties goes here
                       set cell::Range::Font::Name to "verdana"
                       set cell::Range::Font::Size to 10
                       *>cell.Range.Font.ColorIndex = WdColorIndex.wdGray25;                            
                       set cell::Shading::BackgroundPatternColor to type WdColor::wdColorGray25
                       *>Center alignment for the Header cells
                       set cell::VerticalAlignment to type WdCellVerticalAlignment::wdCellAlignVerticalCenter
                       set cell::Range::ParagraphFormat::Alignment to type WdParagraphAlignment::wdAlignParagraphCenter
                    *>Data row
                    else
                       set cell::Range::Text to (cell::RowIndex - 2 + cell::ColumnIndex)::ToString
                    end-if
                 end-perform
              end-perform
                
              *>Save the document
              declare filename as object = "c:\temp\temp1.docx"
              invoke document::SaveAs2(filename, by reference missing, by reference missing, by reference missing
                 by reference missing, by reference missing, by reference missing, by reference missing, by reference missing
                 by reference missing, by reference missing, by reference missing, by reference missing, by reference missing
                 by reference missing, by reference missing, by reference missing)
              invoke document::Close(by reference missing, by reference missing, by reference missing)
              set document to null
              invoke winword::Quit(by reference missing, by reference missing, by reference missing)
              set winword to null
              invoke type MessageBox::Show("Document created successfully !")
            
           catch ex as type Exception
              invoke type MessageBox::Show(ex::Message)
           end-try
           goback.
           
       end program Program1.

View solution in original post

0 Likes
2 Replies
Highlighted
Micro Focus Expert
Micro Focus Expert

RE: Visual COBOL Personal Edition - how to write out a MS-Word document

Jump to solution

Are you looking to do this in native code or managed code?

MS Word is accessible through a COM class in native code or through an interop class under .NET. Both allow you to create documents programatically.

The following is an example which is provided with Net Express for creating a Word document from a native COBOL application using COM:

      *> This is required for OLE applications
      $set ooctrl(+P)

      ****************************************************************
      * Copyright (C) 1997-1999 Micro Focus International Ltd.
      * All Rights Reserved.
      ****************************************************************
      * The program demonstrates the use of OLE Automation to        *
      * send messages to objects in another application. This        *
      * example uses Microsoft Word.                                 *
      *                                                              *
      * It also demonstrates exception handling with regard to OLE   *
      * objects, and the OLE support timeout method.                 *
      *                                                              *
      * The Word interface is documented in the file vbawrd8.hlp     *
      * shipped with Microsoft Word 97 and vbawrd9.chm shipped       *
      * with Microsoft Word 2000.                                    *
      *                                                              *
      * REQUIREMENTS: Microsoft Word 97 or above needs to be         *
      * installed.                                                   *
      *                                                              *
      * $(#) V1.0                                                    *
      ****************************************************************

       program-id. worddemo.

       class-control.
       *> Native Object COBOL classes
           olesup is class "olesup"           *> OLE support class
       *> OLE automation classes
           wordapp is class "$OLE$word.application"
           .

       working-storage section.
       01 wordServer       object reference value null.
       01 theDocument      object reference value null.
       01 theDocuments     object reference value null.
       01 theSelection     object reference value null.
       01 theFind          object reference value null.
       01 theParagraph     object reference value null.
       01 theParagraphs    object reference value null.
       01 theRange         object reference value null.

       01 found            pic s9(9) comp-5.

       procedure division.
           *> Set the timeout for the OLE "busy" error to 100ms
           *> Using this method is recommended for Word applications
           invoke olesup "setOLEBusyTimeout" using by value 100

           *> Create an instance of Word
           invoke wordapp "new" returning wordServer

           *> Make it visible
           invoke wordServer "SetVisible" using by value 1

           *> Get the Word documents collection object
           invoke wordServer "getDocuments" returning theDocuments

           *> Create a new document. The Template and NewTemplate
           *> parameters for this method are optional
           invoke theDocuments "add"

           *> We no longer need the Documents collection
           invoke theDocuments "finalize" returning theDocuments

           *> Get the current selection
           invoke wordServer "getSelection" returning theSelection

           *> Insert some lines of text in the new document
           invoke theSelection "InsertAfter" using
                                      "This is a test line" & x"0d"
           invoke theSelection "InsertAfter" using
                                     "This is the third line" & x"0d"

           *> Finished with the selection object
           invoke theSelection "finalize" returning theSelection

           *> Oops - we've put "third" instead of "second"
           *> So, we'll replace that word. This is a bit convoluted,
           *> but it's intended to give an idea of how collections work

           *> Get the active document
           invoke wordServer "getActiveDocument" returning theDocument

           *> Get the Paragraphs collection, then the second paragraph
           *> using the item method, then the range of that paragraph;
           *> Once we have the range, we've finished with paragraphs!
           *> This does *exactly* the same as the VB command
           *>   Range = Document.Paragraphs(2).Range
           invoke theDocument "getParagraphs" returning theParagraphs
           invoke theParagraphs "item" using by value 2
                               returning theParagraph
           invoke theParagraph "getRange" returning theRange
           invoke theParagraph "finalize" returning theParagraph
           invoke theParagraphs "finalize" returning theParagraphs

           *> Get the Find object and ask it to find the text "third"
           *> This should change theRange object's character range
           invoke theRange "getFind" returning theFind
           invoke theFind "setForward" using by value 1
           invoke theFind "setText" using by content z"third"
           invoke theFind "execute"
           invoke theFind "getFound" returning found
           invoke theFind "finalize" returning theFind

           if found not = 0
               *> Select our new range of characters
               invoke theRange "select"

               *> Finally, change the word to the correct word!
               invoke theRange "setText" using "second"
           end-if
           invoke theRange "finalize" returning theRange

           *> Print the document out
           invoke theDocument "PrintOut" using by value 0

           *> Close it without saving it
           invoke theDocument "Close" using by value 0

           *> We've finished with the document object
           invoke theDocument "finalize" returning theDocument

           *> Tell Word to quit (it won't shut down otherwise)
           invoke wordServer "quit"

           *> We've now finished with the Word object
           invoke wordServer "finalize" returning wordServer

           exit program
           stop run.



The following is a managed code .NET application that uses the Interop class:

      $set ilusing"System.Windows.Forms"
      $set ilusing"Microsoft.Office.Interop.Word" 
       program-id. Program1 as "testnetword.Program1".
       data division.
       working-storage section.
       01 winword type Microsoft.Office.Interop.Word.Application.
       01 document type Document.
       01 headerRange type Range.
       01 footerRange type Range.
       01 para1 type Paragraph.
       01 para2 type Paragraph.
       01 firstTable type Table.
       01 myHeaderFooter type WdHeaderFooterIndex value type WdHeaderFooterIndex::wdHeaderFooterPrimary.
       procedure division.
 
           try
              *>Create an instance for word app
              set winword to new Microsoft.Office.Interop.Word.Application
              *>Set status for word application is to be visible or not.
              set winword::Visible to false
              *>Create a missing variable for missing value
              declare missing as object = type System.Reflection.Missing::Value
              *>Create a new document
              set document to winword::Documents::Add(by reference missing, by reference missing, by reference missing, by reference missing)
              *>Add header into the document
              perform varying mysection as type Section thru document::Sections
                 *>Get the header range and add the header details.
                 set headerRange to mysection::Headers[myHeaderFooter]::Range
                 invoke headerRange::Fields::Add(headerRange, type WdFieldType::wdFieldPage as object, by reference missing, by reference missing)
                 set headerRange::ParagraphFormat::Alignment to type WdParagraphAlignment::wdAlignParagraphCenter
                 set headerRange::Font::ColorIndex to type WdColorIndex::wdBlue
                 set headerRange::Font::Size to 10
                 set headerRange::Text to "Header text goes here"
              end-perform

              *>Add the footers into the document
              perform varying wordSection as type Section thru document::Sections
                 *>Get the footer range and add the footer details.
                 set footerRange to wordSection::Footers[myHeaderFooter]::Range
                 set footerRange::Font::ColorIndex to type WdColorIndex::wdDarkRed
                 set footerRange::Font::Size to 10
                 set footerRange::ParagraphFormat::Alignment to type WdParagraphAlignment::wdAlignParagraphCenter
                 set footerRange::Text to "Footer text goes here"
              end-perform
  
              *>adding text to document
              invoke document::Content::SetRange(0, 0)
              set document::Content::Text to "This is test document " & type Environment::NewLine
  
              *>Add paragraph with Heading 1 style
              set para1 to document::Content::Paragraphs::Add(by reference missing)
              declare styleHeading1 as object = "Heading 1"
              invoke para1::Range::set_Style(by reference styleHeading1)
              set para1::Range::Text to "Para 1 text"
              invoke para1::Range::InsertParagraphAfter

              *>Add paragraph with Heading 2 style
              set para2 to document::Content::Paragraphs::Add(by reference missing)
              declare styleHeading2 as object = "Heading 2"
              invoke para2::Range::set_Style(by reference styleHeading2)
              set para2::Range::Text to "Para 2 text"
              invoke para2::Range::InsertParagraphAfter

              *>Create a 5X5 table and insert some dummy record
              set firstTable to document::Tables::Add(para1::Range, 5, 5, by reference missing, by reference missing)
              set firstTable::Borders::Enable to 1
              perform varying row as type Row thru firstTable::Rows
                 perform varying cell as type Cell thru row::Cells
                    *>Header row
                    if cell::RowIndex = 1
                       set cell::Range::Text to "Column " & cell::ColumnIndex::ToString
                       set cell::Range::Font::Bold to 1
                       *>other format properties goes here
                       set cell::Range::Font::Name to "verdana"
                       set cell::Range::Font::Size to 10
                       *>cell.Range.Font.ColorIndex = WdColorIndex.wdGray25;                            
                       set cell::Shading::BackgroundPatternColor to type WdColor::wdColorGray25
                       *>Center alignment for the Header cells
                       set cell::VerticalAlignment to type WdCellVerticalAlignment::wdCellAlignVerticalCenter
                       set cell::Range::ParagraphFormat::Alignment to type WdParagraphAlignment::wdAlignParagraphCenter
                    *>Data row
                    else
                       set cell::Range::Text to (cell::RowIndex - 2 + cell::ColumnIndex)::ToString
                    end-if
                 end-perform
              end-perform
                
              *>Save the document
              declare filename as object = "c:\temp\temp1.docx"
              invoke document::SaveAs2(filename, by reference missing, by reference missing, by reference missing
                 by reference missing, by reference missing, by reference missing, by reference missing, by reference missing
                 by reference missing, by reference missing, by reference missing, by reference missing, by reference missing
                 by reference missing, by reference missing, by reference missing)
              invoke document::Close(by reference missing, by reference missing, by reference missing)
              set document to null
              invoke winword::Quit(by reference missing, by reference missing, by reference missing)
              set winword to null
              invoke type MessageBox::Show("Document created successfully !")
            
           catch ex as type Exception
              invoke type MessageBox::Show(ex::Message)
           end-try
           goback.
           
       end program Program1.

View solution in original post

0 Likes
Highlighted
Absent Member.
Absent Member.

RE: Visual COBOL Personal Edition - how to write out a MS-Word document

Jump to solution

It is the Native I am using

Thanks very much

It looks to be just what I need

0 Likes
The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.