PB - MS WORD OLE

Helo,

I have following problem. I want only to write some data read from DB in PB
to a Word docment and then to print it out. I am using OLE - everything is
OK - I am connected to MS Word, the file is opened, I can even print it
...., but I can't manage to write on a bookmark. I have already tried
following, but nothing works:

ole_word.object.Application.ActiveDocument.Bookmarks("testbook").Range.Text
= "test value"

Since I know that there can be troubles with bookmarks (defined x
notdefined) in Word I thought that maybe it could be better to use the
bookmarks check in VBA via my macro:

macro: this works started directly from Word:
Public Sub testmacro()

If Application.ActiveDocument.Bookmarks.Exists("testbook") Then
    Application.ActiveDocument.Bookmarks("testbook").Range.Text = "test
value"
End If

End Sub

but then I am not able to call the Word function (macro) from PB script.
None of following works:

ole_word.Object.wordbasic.testmacro
ole_word.Object.testmacro
ole_word.Object.Call testmacro - this causes compilation error

??? Is it possible to call Word macros from PB or how to directly set the
Bookmarks value ???

Thanks for any help

Jiri
0
Jiri
2/10/2000 6:38:38 PM
sybase.ole-ocx-activex 6324 articles. 0 followers. Follow

4 Replies
727 Views

Similar Articles

[PageSpeed] 12
Get it on Google Play
Get it on Apple App Store

It's really interesting how the command is dependant on the version. We
have Word 97 SR-2 and imagine what is working:

ole_word.Object.Application.Documents.Open(ls_file)
ole_word.Object.Application.Run(ls_macro) //!!!!!!!
ole_word.Object.Application.ActiveDocument.PrintOut
ole_word.Object.Application.ActiveDocument.Close()

Jiri <Jiri.Felcman@noofs.abb.no> wrote in article
<01bf73f5$2d738370$ca948589@nooft-w75108350>...
> Helo,
> 
> I have following problem. I want only to write some data read from DB in
PB
> to a Word docment and then to print it out. I am using OLE - everything
is
> OK - I am connected to MS Word, the file is opened, I can even print it
> ..., but I can't manage to write on a bookmark. I have already tried
> following, but nothing works:
> 
>
ole_word.object.Application.ActiveDocument.Bookmarks("testbook").Range.Text
> = "test value"
> 
> Since I know that there can be troubles with bookmarks (defined x
> notdefined) in Word I thought that maybe it could be better to use the
> bookmarks check in VBA via my macro:
> 
> macro: this works started directly from Word:
> Public Sub testmacro()
> 
> If Application.ActiveDocument.Bookmarks.Exists("testbook") Then
>     Application.ActiveDocument.Bookmarks("testbook").Range.Text = "test
> value"
> End If
> 
> End Sub
> 
> but then I am not able to call the Word function (macro) from PB script.
> None of following works:
> 
> ole_word.Object.wordbasic.testmacro
> ole_word.Object.testmacro
> ole_word.Object.Call testmacro - this causes compilation error
> 
> ??? Is it possible to call Word macros from PB or how to directly set the
> Bookmarks value ???
> 
> Thanks for any help
> 
> Jiri
> 
0
Jiri
2/10/2000 7:38:29 PM
BUT - This doesn't work if you want to start macros (VBA procedures) with
parameters. WHY ???

Jiri <Jiri.Felcman@noofs.abb.no> wrote in article
<01bf73fd$888e23c0$ca948589@nooft-w75108350>...
> It's really interesting how the command is dependant on the version. We
> have Word 97 SR-2 and imagine what is working:
> 
> ole_word.Object.Application.Documents.Open(ls_file)
> ole_word.Object.Application.Run(ls_macro) //!!!!!!!
> ole_word.Object.Application.ActiveDocument.PrintOut
> ole_word.Object.Application.ActiveDocument.Close()
> 
> Jiri <Jiri.Felcman@noofs.abb.no> wrote in article
> <01bf73f5$2d738370$ca948589@nooft-w75108350>...
> > Helo,
> > 
> > I have following problem. I want only to write some data read from DB
in
> PB
> > to a Word docment and then to print it out. I am using OLE - everything
> is
> > OK - I am connected to MS Word, the file is opened, I can even print it
> > ..., but I can't manage to write on a bookmark. I have already tried
> > following, but nothing works:
> > 
> >
>
ole_word.object.Application.ActiveDocument.Bookmarks("testbook").Range.Text
> > = "test value"
> > 
> > Since I know that there can be troubles with bookmarks (defined x
> > notdefined) in Word I thought that maybe it could be better to use the
> > bookmarks check in VBA via my macro:
> > 
> > macro: this works started directly from Word:
> > Public Sub testmacro()
> > 
> > If Application.ActiveDocument.Bookmarks.Exists("testbook") Then
> >     Application.ActiveDocument.Bookmarks("testbook").Range.Text = "test
> > value"
> > End If
> > 
> > End Sub
> > 
> > but then I am not able to call the Word function (macro) from PB
script.
> > None of following works:
> > 
> > ole_word.Object.wordbasic.testmacro
> > ole_word.Object.testmacro
> > ole_word.Object.Call testmacro - this causes compilation error
> > 
> > ??? Is it possible to call Word macros from PB or how to directly set
the
> > Bookmarks value ???
> > 
> > Thanks for any help
> > 
> > Jiri
> > 
> 
0
Jiri
2/11/2000 9:28:13 AM
Here is a small sample of commands that we use when communicating with MS
Word.



OLEObject iole_word
STRING ls_doc
STRING ls_bookmarkname
STRING ls_bookmarkvalue

// Set variables
ls_doc = "mydoc.doc" // replace with db value if necessary
ls_bookmarkname = "state_value" // replace with db value if necessary
ls_bookmarkvalue = "California" // replace with db value if necessary

// Instantiate oleobject
iole_word = CREATE oleobject

// Connect to Word
iole_word.ConnectToNewObject("word.application.8")

// Open Doc
iole_word.Documents.Open(ls_doc)

// Goto bookmark and insert bookmarkvalue (option #1)
iole_word.ActiveDocument.Bookmarks.Item(ls_bookmarkname).Range.Text =
ls_bookmarkvalue

// Goto bookmark and insert bookmarkvalue (option #2)
// Note: this is derived from word.basic (word95) when you had
// to goto the bookmark and typetext your bookmarkvalue)
iole_word.ActiveDocument.Bookmarks.Item(ls_bookmarkname).Select
iole_word.Selection.TypeText(ls_bookmarkvalue)

// Print Doc (w/ defaults)
iole_word.ActiveDocument.PrintOut()

// Close Doc (w/o saving)
iole_word.Documents.Close(0)

// Exit Word
iole_word.Application.Quit(0)

// Disconnect and destroy instance
iole_word.DisconnectObject()
Destroy iole_word

/////////////////////////////////////////////////////////////////
// Additional Word Commands
// Note: all of these can be found by
// creating a macro in ms word and
// converting to PB code. All of these
// work for all versions of Word 97 I have
// tested (sr0, sr1, & sr2).
//
// make word visible/invisible
// iole_word.Visible = True
// iole_word.Visible = False
//
// goto start of document
// iole_word.Selection.HomeKey(6)
//
// goto end of document
// iole_word.Selection.EndKey(6)
//
// goto beginning of current line
// iole_word.Selection.HomeKey(5,x)
// x = 0 [does not hold down shift key]
// x = 1 [hold down shift key]
//
// goto end of current line
// iole_word.Selection.EndKey(5,x)
// x = 0 [does not hold down shift key]
// x = 1 [hold down shift key]
//
// delete current selection
// iole_word.Selection.Delete()
//
// enter new line
// iole_word.Selection.TypeParagraph()
//
// move cursor right
// iole_word.Selection.MoveRight(x,y,z)
// x = 1 [move # of letters to right]
// x = 2 [move # of words to right]
// x = 3 [move # of sentences to right]
// y = # [number to move right]
// z = 0 [does not hold down shift key]
// z = 1 [hold down shift key]
//
// move cursor left
// iole_word.Selection.MoveLeft(x,y,z)
// x = 1 [move # of letters to left]
// x = 2 [move # of words to left]
// x = 3 [move # of sentences to left]
// y = # [number to move left]
// z = 0 [does not hold down shift key]
// z = 1 [hold down shift key]
//
/////////////////////////////////////////////////////////////////
// sample find/replace all (this will not
// prompt the user once it starts)
//

ls_find = sle_find.Text  // find text sle
ls_repl = sle_replace.Text   // replace text sle
lb_matchcase = cbx_matchcase.Checked  // match case checkbox

// perform initial find
iole_word.Selection.Find.MatchCase = lb_matchcase
iole_word.Selection.Find.Text = ls_find
lb_found = iole_word.Selection.Find.Execute()

// replace text and look for next until no more are found
DO WHILE lb_found
    ll_rc +=1
    iole_word.Selection.TypeText(ls_repl)
    iole_word.Selection.Find.Text = ls_find
    sle_replaced.Text = STRING(ll_rc)  // show user how many replaced
    lb_found = iole_word.Selection.Find.Execute()
LOOP

//
// End of find/replace all
/////////////////////////////////////////////////////////////////




Jiri <Jiri.Felcman@noofs.abb.no> wrote in message
news:01bf73f5$2d738370$ca948589@nooft-w75108350...
> Helo,
>
> I have following problem. I want only to write some data read from DB in
PB
> to a Word docment and then to print it out. I am using OLE - everything is
> OK - I am connected to MS Word, the file is opened, I can even print it
> ..., but I can't manage to write on a bookmark. I have already tried
> following, but nothing works:
>
>
ole_word.object.Application.ActiveDocument.Bookmarks("testbook").Range.Text
> = "test value"
>
> Since I know that there can be troubles with bookmarks (defined x
> notdefined) in Word I thought that maybe it could be better to use the
> bookmarks check in VBA via my macro:
>
> macro: this works started directly from Word:
> Public Sub testmacro()
>
> If Application.ActiveDocument.Bookmarks.Exists("testbook") Then
>     Application.ActiveDocument.Bookmarks("testbook").Range.Text = "test
> value"
> End If
>
> End Sub
>
> but then I am not able to call the Word function (macro) from PB script.
> None of following works:
>
> ole_word.Object.wordbasic.testmacro
> ole_word.Object.testmacro
> ole_word.Object.Call testmacro - this causes compilation error
>
> ??? Is it possible to call Word macros from PB or how to directly set the
> Bookmarks value ???
>
> Thanks for any help
>
> Jiri


0
Tom
3/17/2000 4:34:49 PM
The iole_word.Selection.TypeText command works, but what if I want to bring
in a bmp file.

would it be iole_word.Selection.TypePicture?



Tom Bratina wrote in message ...
>Here is a small sample of commands that we use when communicating with MS
>Word.
>
>
>
>OLEObject iole_word
>STRING ls_doc
>STRING ls_bookmarkname
>STRING ls_bookmarkvalue
>
>// Set variables
>ls_doc = "mydoc.doc" // replace with db value if necessary
>ls_bookmarkname = "state_value" // replace with db value if necessary
>ls_bookmarkvalue = "California" // replace with db value if necessary
>
>// Instantiate oleobject
>iole_word = CREATE oleobject
>
>// Connect to Word
>iole_word.ConnectToNewObject("word.application.8")
>
>// Open Doc
>iole_word.Documents.Open(ls_doc)
>
>// Goto bookmark and insert bookmarkvalue (option #1)
>iole_word.ActiveDocument.Bookmarks.Item(ls_bookmarkname).Range.Text =
>ls_bookmarkvalue
>
>// Goto bookmark and insert bookmarkvalue (option #2)
>// Note: this is derived from word.basic (word95) when you had
>// to goto the bookmark and typetext your bookmarkvalue)
>iole_word.ActiveDocument.Bookmarks.Item(ls_bookmarkname).Select
>iole_word.Selection.TypeText(ls_bookmarkvalue)
>
>// Print Doc (w/ defaults)
>iole_word.ActiveDocument.PrintOut()
>
>// Close Doc (w/o saving)
>iole_word.Documents.Close(0)
>
>// Exit Word
>iole_word.Application.Quit(0)
>
>// Disconnect and destroy instance
>iole_word.DisconnectObject()
>Destroy iole_word
>
>/////////////////////////////////////////////////////////////////
>// Additional Word Commands
>// Note: all of these can be found by
>// creating a macro in ms word and
>// converting to PB code. All of these
>// work for all versions of Word 97 I have
>// tested (sr0, sr1, & sr2).
>//
>// make word visible/invisible
>// iole_word.Visible = True
>// iole_word.Visible = False
>//
>// goto start of document
>// iole_word.Selection.HomeKey(6)
>//
>// goto end of document
>// iole_word.Selection.EndKey(6)
>//
>// goto beginning of current line
>// iole_word.Selection.HomeKey(5,x)
>// x = 0 [does not hold down shift key]
>// x = 1 [hold down shift key]
>//
>// goto end of current line
>// iole_word.Selection.EndKey(5,x)
>// x = 0 [does not hold down shift key]
>// x = 1 [hold down shift key]
>//
>// delete current selection
>// iole_word.Selection.Delete()
>//
>// enter new line
>// iole_word.Selection.TypeParagraph()
>//
>// move cursor right
>// iole_word.Selection.MoveRight(x,y,z)
>// x = 1 [move # of letters to right]
>// x = 2 [move # of words to right]
>// x = 3 [move # of sentences to right]
>// y = # [number to move right]
>// z = 0 [does not hold down shift key]
>// z = 1 [hold down shift key]
>//
>// move cursor left
>// iole_word.Selection.MoveLeft(x,y,z)
>// x = 1 [move # of letters to left]
>// x = 2 [move # of words to left]
>// x = 3 [move # of sentences to left]
>// y = # [number to move left]
>// z = 0 [does not hold down shift key]
>// z = 1 [hold down shift key]
>//
>/////////////////////////////////////////////////////////////////
>// sample find/replace all (this will not
>// prompt the user once it starts)
>//
>
>ls_find = sle_find.Text  // find text sle
>ls_repl = sle_replace.Text   // replace text sle
>lb_matchcase = cbx_matchcase.Checked  // match case checkbox
>
>// perform initial find
>iole_word.Selection.Find.MatchCase = lb_matchcase
>iole_word.Selection.Find.Text = ls_find
>lb_found = iole_word.Selection.Find.Execute()
>
>// replace text and look for next until no more are found
>DO WHILE lb_found
>    ll_rc +=1
>    iole_word.Selection.TypeText(ls_repl)
>    iole_word.Selection.Find.Text = ls_find
>    sle_replaced.Text = STRING(ll_rc)  // show user how many replaced
>    lb_found = iole_word.Selection.Find.Execute()
>LOOP
>
>//
>// End of find/replace all
>/////////////////////////////////////////////////////////////////
>
>
>
>
>Jiri <Jiri.Felcman@noofs.abb.no> wrote in message
>news:01bf73f5$2d738370$ca948589@nooft-w75108350...
>> Helo,
>>
>> I have following problem. I want only to write some data read from DB in
>PB
>> to a Word docment and then to print it out. I am using OLE - everything
is
>> OK - I am connected to MS Word, the file is opened, I can even print it
>> ..., but I can't manage to write on a bookmark. I have already tried
>> following, but nothing works:
>>
>>
>ole_word.object.Application.ActiveDocument.Bookmarks("testbook").Range.Text
>> = "test value"
>>
>> Since I know that there can be troubles with bookmarks (defined x
>> notdefined) in Word I thought that maybe it could be better to use the
>> bookmarks check in VBA via my macro:
>>
>> macro: this works started directly from Word:
>> Public Sub testmacro()
>>
>> If Application.ActiveDocument.Bookmarks.Exists("testbook") Then
>>     Application.ActiveDocument.Bookmarks("testbook").Range.Text = "test
>> value"
>> End If
>>
>> End Sub
>>
>> but then I am not able to call the Word function (macro) from PB script.
>> None of following works:
>>
>> ole_word.Object.wordbasic.testmacro
>> ole_word.Object.testmacro
>> ole_word.Object.Call testmacro - this causes compilation error
>>
>> ??? Is it possible to call Word macros from PB or how to directly set the
>> Bookmarks value ???
>>
>> Thanks for any help
>>
>> Jiri
>
>


0
Oliver
4/5/2000 2:43:24 AM
Reply:

Similar Artilces:

can i use pb's automation server to create an activex/ole/ocx? help me!
Please do not cross-post. -- <hopethishelps/> Roy Kiesler [TeamSybase] MySybase -- http://www.sybase.com/mysybase "tadsun" <tadsun@163.com> wrote in message news:UXo0Ru7BCHA.201@forums.sybase.com... > > > ...

PB to create OLE and OLE with PD
It works great to reuse NVO's from Powerbuilder within PD. Excellent! D. Baer Sybase CH Works great to create instances of Jaguar COM proxies too! <!--SCRIPT comp = CreateObject("SVU.SVULogin"); comp.Username="jagadmin"; comp.Password=""; comp.Host="localhost:9000"; comp.Initialize(); if(comp.isLogin("123-45-6789") { document.writeln("Login successful"); } --> Dave Wolf Jaguar Product Team Dominik Baer wrote: > It works great to reuse NVO's from Powerbuilder within PD. > Ex...

PB Word OLE
I am using an OLE control to open and print a Word Document. I would like to print the document to Papertray 2 rather than the default tray. I have tried the following pb code to accomplish this but both return errors. wordapp.ActiveDocument.PageSetup.FirstPageTray(2) wordapp.ActiveDocument.PageSetup.OtherPagesTray(2) and wordapp.ActiveDocument.PageSetup.FirstPageTray = 2 wordapp.ActiveDocument.PageSetup.OtherPagesTray = 2 Thanks in advance ...

PB to Word, OLE
I connect to Word 97 with PB7. That works fine. Now I want to save the word document and send the filename from word to PB. How have I access to my current PowerBuilder application? How can I call a function from PB in Word? I tried it in Word with GetObject fo getting my Powerbuilder Application, but this didn't work.... Thanks. ...

PB
Hello: I would like to open word, excel files within a powerbuilder application in read-only mode. And I do not want the menu and toolbar of the word, excel application to be displayed. Is there a way to hide the menu and toolbar? Any help will be greatly appreciated. Thanks Mathi Hi Check for the "DsoFramer" control. (Microsoft Developer Support Office Framer Control 1.2 Sample (MSDN - KB311765)) Alexei "MAthi" <smathioli@yahoo.com> �������/�������� � �������� ���������: news:4448f089$1@forums-2-dub... > > Hello: > ...

PB and Word OLE
FWIW - Here is some OLE automation stuff for Word 97. I will be updating this shortly, but another member had asked about this as well. ** Apply Microsoft Word SR-1 for Office 97 ** Seems to speed up OLE. Word 97 OLE Automation with PowerBuilder 5.x + There are several examples of Word OLE with Word 95, but few for Word 97. Word 97 uses VB for Applications(VBA) as it's scripting language and therefore makes the previous examples "legacy." Describe below are some common OLE method you may want to call to communicate with Word 97. The best resources for more i...

word 2000 and PB7.0 as activex via ole control -- to disable the users ablitty to print outside of the pb application
Hello everyone, I have an application that needs to control the printing of customized documents. we are using word 2000 via an activex control within PB 7.02 ole control. The process works for the most of the time. However, when we disable all the toolbars/command bars the activex control does not want to return control back to pb (sometimes). A simple action of clicking on the vertical scrollbar in the activex control does release control back to the PB script to complete its processing. These docs are protected but the reason for removing the toolbars/command bars is to rem...

OLE-Word Header/Footer
Hi all I've searched the sites but haven't found info on this so I apologize if this a FAQ; We're using OLE to create/modify Word documents and saving them as a Blob in our DB; problem is that Header/Footer information doesn't seem to want to save in any consistent manner; sometimes it will, sometimes it won't. We use a mail-merge with a blank template to create the document. TIA Philippe I'm having the same problem. Have you had any success finding a resolution? -- John De Lello DelWare Software Solutions, LLC Programming solutions for...

PB - Word 8
>I am using PB6.5 attaching to word8 using ole. Everything works find except >when you cancel a print job. It returns an error to PowerBuilder, "Error >accessing external object 'execute' " and PowerBuilder will bomb. >How do I correct this situation? >Thanks, >Mike Mike, I don't think I am the right person to be answering this one. I have placed this in the PB - General newsgroup to see if someone else may be more aware of what might be going on. FWIW Jon Credit[TeamSybase] DONT_SPAM_ME_JCredit@Sprynet.com http://jcredit.home.sprynet.co...

OLE Word97 and ole objects vs ole controls
--------------50D299EA9D99A20C83E801AB Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit I am new to OLE automation. I'm trying to connect to a word97 document and filling forms fields with information. I'm trying to use the following code. I'm getting the following error in my log file: DateTime: 10/27/99 18:32:07 Title: System Error Message: Error Number 36. Error text = Name not found accessing external object property object. Window/Menu/Object = w_ole_test. Error Object/Control = cb_okay. Script = clicked. Line in Script = 22. ...

VB OCX
Hi, i have created a OCX using VB6 then i'm calling it from PB8 through OLE. A function inside the OCX has a parameter that is set byref. however, after triggering the function from PB, the value from the OCX function is not being sent back. Is this a restriction or am i just missing out someting? Thanks and Regards, Mickey I hope I get this right. Try adding a REF statement in your function call. ole_1.Object.Function(REF ls_var) Brad Mickey wrote: > Hi, > > i have created a OCX using VB6 then i'm calling it from PB8 > through OLE. A functio...

OLE Word97 and ole objects vs ole controls
--------------50D299EA9D99A20C83E801AB Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit I am new to OLE automation. I'm trying to connect to a word97 document and filling forms fields with information. I'm trying to use the following code. I'm getting the following error in my log file: DateTime: 10/27/99 18:32:07 Title: System Error Message: Error Number 36. Error text = Name not found accessing external object property object. Window/Menu/Object = w_ole_test. Error Object/Control = cb_okay. Script = clicked. Line in Script = 22. ...

OLE Microsoft Word and PB 7
Has anyone had any issues using OLE command and PB7. I have a large script which uses OLE to pass about (100) distinct data elements to Microsoft Word bookmarks. The script functions fine 99% of the time and will fail in the same place each time, different data items. The code will fail on the Selection.Goto line with the message like error acessing external ........... if ole_OleObject.ActiveDocument.BookMarks.Exists(s_BookMarkName) then ole_OleObject.Selection.Goto(-1,0,0,s_BookMarkName) ole_OleObject.Selection.TypeText(s_BookMarkData) end if Again it w...

PB with ole object richtx32.ocx
Hello, I use a user object with a richtx32.ocx ole object in a window, and i have a problem with the getfocus in this user obejct : when i always use TAB key it's ok, but when i losefocus my user object with the mouse, after the TAB key doesn't work, i'm oblige to click on my user object. thanks ...

PB 7 objects and OLE,OCX
Could a PB7 picture object be exported in an OCX or OLE object in order to be used in previous versions? Chriss cioannou@bankofcyprus.gr ...

Web resources about - PB - MS WORD OLE - sybase.ole-ocx-activex

Word Aligned
A collection of articles on software development written by Thomas Guest.

Word search - Wikipedia, the free encyclopedia
A word search , word find , word seek , word sleuth or mystery word puzzle is a word game that is letters of a word in a grid, that usually has ...

From today's Lectionary: In the beginning was the Word
John 1:(1-9), 10-18 1:1 In the beginning was the Word, and the Word was with God, and the Word was God. 1:2 He was in the beginning with God. ...

Today’s apps gone free: Monster vs Sheep, Bloom Box, Compound Word Match and more
Save a coastal city from total destruction, create blossoming chain reactions, and learn about compound words with todays collection of apps ...

Shabab turns Hillary's words into truth.
"During a Democratic presidential debate last month, Hillary Clinton said that Mr. Trump had been used in a recruitment video for the Islamic ...

The Willy Loman Of American Politics: Of Herr Trumpf's Five Most Used Words, #1 Is "I" And #4 is "Trump" ...
... can understand a thing he's saying? Flattening the English language whenever he speaks without a script, Trump relies heavily on words such ...

T-Mobile and YouTube are fighting over the word 'throttling' — and it has big implications for the future ...
... total control to turn the service off or on at will. With our approach, customers win, our partners win, we win." The fight over the wording ...

These words, phrases have been declared problematic
41st annual fun list from Lake Superior State University has even dozen, including one appearing for 2nd time, used differently

The Story of Life in Images and Words
The LIFE Project is a poetic collection of photographs that tell the story of our planet, from its eruptive beginnings to its present diversity ...

Trump: ‘I Know Words, I Have The Best Words’ — Obama Is ‘Stupid’
Trump: ‘I Know Words, I Have The Best Words’ — Obama Is ‘Stupid’

Resources last updated: 1/3/2016 7:59:23 PM