<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>LibreOffice &#8211; tutolibro.org</title>
	<atom:link href="https://tutolibro.org/category/libreoffice/feed/" rel="self" type="application/rss+xml" />
	<link>https://tutolibro.org</link>
	<description>Free online tutorials</description>
	<lastBuildDate>Thu, 27 Nov 2025 22:59:18 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.3</generator>

<image>
	<url>https://tutolibro.org/wp-content/uploads/2020/02/cropped-logo_mini-32x32.png</url>
	<title>LibreOffice &#8211; tutolibro.org</title>
	<link>https://tutolibro.org</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">173775150</site>	<item>
		<title>Assign Your Python Macro to a Button in LibreOffice Calc</title>
		<link>https://tutolibro.org/2025/11/26/assign-your-python-macro-to-a-button-in-libreoffice/</link>
					<comments>https://tutolibro.org/2025/11/26/assign-your-python-macro-to-a-button-in-libreoffice/#respond</comments>
		
		<dc:creator><![CDATA[gweno]]></dc:creator>
		<pubDate>Wed, 26 Nov 2025 16:03:15 +0000</pubDate>
				<category><![CDATA[Calc]]></category>
		<category><![CDATA[LibreOffice]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[calc]]></category>
		<category><![CDATA[hello world]]></category>
		<category><![CDATA[libreoffice]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">https://tutolibro.org/?p=1555</guid>

					<description><![CDATA[Assign the macro to a LibreOffice Control Button. When you write a macro within libreOffice, you will quickly realise something. It&#8217;s not really convenient to execute macros through the Macro Manager. This is because you need to access that menu,...<br /><a class="read-more-button" href="https://tutolibro.org/2025/11/26/assign-your-python-macro-to-a-button-in-libreoffice/">Read more</a>]]></description>
										<content:encoded><![CDATA[
<h4 class="wp-block-heading" id="top"> Assign the macro to a LibreOffice Control Button.</h4>



<p id="switch">When you write a macro within libreOffice, you will quickly realise something. It&#8217;s not really convenient to execute macros through the Macro Manager. This is because you need to access that menu, and it takes a few clicks to do so. (Quickest way to access the APSO Macro manager being [Alt] + [Shift] + [F11]). Creating a button on your spreadsheet is easy. You can assign this button to your macro. When you click on the button, it will execute the macro.<br>So first we&#8217;ll <strong><a href="#switch">Switch to Design Mode</a></strong>. This allows us to <strong><a href="#button">create a button</a></strong> on the spreadsheet. Then, we&#8217;ll <strong><a href="#assign">assign the python macro</a></strong> to this button.</p>



<p><strong><span style="text-decoration: underline;">Switch to Design Mode</span></strong>:                                                                                                            (<a href="#top">Back to Top</a>)</p>



<p>The first step is to set the document to &#8216;Design Mode&#8217; . Select &#8216;Design Mode&#8217; From &#8216;Menu Tools/Forms/Design Mode&#8217;.</p>



<figure class="wp-block-image size-full" id="button"><img fetchpriority="high" decoding="async" width="555" height="463" src="https://tutolibro.org/wp-content/uploads/2025/11/lopy-designMode-1.png" alt="" class="wp-image-1606" srcset="https://tutolibro.org/wp-content/uploads/2025/11/lopy-designMode-1.png 555w, https://tutolibro.org/wp-content/uploads/2025/11/lopy-designMode-1-300x250.png 300w" sizes="(max-width: 555px) 100vw, 555px" /></figure>



<p><strong><span style="text-decoration: underline;">Create a button</span></strong>:                                                                                                            (<a href="#top">Back to Top</a>)<br>Then simply by clicking on Menu &#8216;<strong>Insert>Form Controls>Push Button&#8217;</strong>:</p>



<figure class="wp-block-image size-full"><img decoding="async" width="492" height="730" src="https://tutolibro.org/wp-content/uploads/2025/11/lopy-InsertPushButtonMenu.png" alt="" class="wp-image-1605" srcset="https://tutolibro.org/wp-content/uploads/2025/11/lopy-InsertPushButtonMenu.png 492w, https://tutolibro.org/wp-content/uploads/2025/11/lopy-InsertPushButtonMenu-202x300.png 202w" sizes="(max-width: 492px) 100vw, 492px" /></figure>



<p>Once you have the little cross to insert the button, click for the button&#8217;s upper left corner. Then hold and release where you want the bottom right corner of the button.</p>



<figure class="wp-block-image size-large is-resized" id="assign"><img decoding="async" width="124" height="84" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc11.png" alt="" class="wp-image-858"/></figure>



<p><strong><span style="text-decoration: underline;">Assign the python macro</span></strong><span style="text-decoration: underline;">:</span>                                                                                                            (<a href="#top">Back to Top</a>)<br>Once you have the button displayed, right click on it and select &#8216;Control&#8230;&#8217;</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="241" height="373" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc12.png" alt="" class="wp-image-859" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc12.png 241w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc12-194x300.png 194w" sizes="auto, (max-width: 241px) 100vw, 241px" /><figcaption class="wp-element-caption">Select &#8216;Control&#8217; from the new Button contextual menu</figcaption></figure>



<p>Then in the window &#8216;Properties&#8217; select the &#8216;Events&#8217; tab, scroll down a bit to find in the list of events the one called &#8216;Mouse button pressed&#8217;. On the right of this &#8216;Mouse button pressed&#8217; entry click on the button &#8216;[&#8230;]&#8217;.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="564" height="430" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc13.png" alt="" class="wp-image-860" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc13.png 564w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc13-300x229.png 300w" sizes="auto, (max-width: 564px) 100vw, 564px" /></figure>



<p>A window named  &#8220;Assign Action&#8217; pops up, click on the button &#8216;[Macro]&#8217; on the right hand side of this window.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="592" height="373" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc14.png" alt="" class="wp-image-861" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc14.png 592w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc14-300x189.png 300w" sizes="auto, (max-width: 592px) 100vw, 592px" /><figcaption class="wp-element-caption">Assign a macro to a button</figcaption></figure>



<p>You should then get the &#8216;Macro Selector&#8217; with your Macro Libraries. Simply go to the library where your macro is saved and select the macro &#8216;HelloWorld&#8217;,then press &#8216;OK&#8217;.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="722" height="202" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc15-e1565986476973.png" alt="" class="wp-image-862" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc15-e1565986476973.png 722w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc15-e1565986476973-300x84.png 300w" sizes="auto, (max-width: 722px) 100vw, 722px" /><figcaption class="wp-element-caption">Select the macro from Macro Selector</figcaption></figure>



<p>Then &#8216;OK&#8217; again in &#8216;Assign Macro&#8217; window, than close the &#8216;Properties&#8217; window.<br>The last thing to do is exit the &#8216;Design&#8217; mode. This allows you to click on the button. Do that by going to &#8216;Tools&gt;Forms&gt;Design Mode&#8217;.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="461" height="541" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc17.png" alt="" class="wp-image-864" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc17.png 461w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc17-256x300.png 256w" sizes="auto, (max-width: 461px) 100vw, 461px" /><figcaption class="wp-element-caption">Set design mode off</figcaption></figure>



<p>And now when you click on the button&#8230; tada&#8230;<br>If you get this ERROR!</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="546" height="255" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc16.png" alt="" class="wp-image-863" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc16.png 546w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc16-300x140.png 300w" sizes="auto, (max-width: 546px) 100vw, 546px" /><figcaption class="wp-element-caption">Error: missing argument</figcaption></figure>



<p>The function HelloWorld requires all information from LibreOffice Context to work. This information is needed in the form of an argument. So we need to pass the argument &#8216;*args&#8217; in your function called by the Push Button.<br>For example in the program HelloWorld done in a previous post, in your code instead of:<br><code>def HelloWorld():</code><br>You should have:<br><code>def HelloWorld(*args):</code><br>Save your program again and then when you press on the button the cell A1 will display &#8216;Hello World!&#8217; !!!</p>



<p>So there is the final version of the macro:</p>



<hr class="wp-block-separator has-css-opacity"/>



<pre class="wp-block-code"><code># Created by Gweno 16/08/2019 for tutolibro.tech
# This program displays 'Hello World!" in cell A1 of the 
# current Calc document.

def HelloWorld(*args):
    """Write 'Hello World!' in Cell A1"""
    
# get the doc from the scripting context 
# which is made available to all scripts
    desktop = XSCRIPTCONTEXT.getDesktop()
    model = desktop.getCurrentComponent()
    
# access the active sheet
    active_sheet = model.CurrentController.ActiveSheet

# write 'Hello World' in A1
    active_sheet.getCellRangeByName("A1").String = "Hello World!"</code></pre>



<p>You can clone or download this code from gitHub <a href="https://github.com/Gweno/tutolibro.tech/tree/master/lopy/part2">here</a>.</p>



<hr class="wp-block-separator has-css-opacity"/>



<h3 class="wp-block-heading">Good luck! and leave a comment if you are having problem to have this macro to work.</h3>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-default"/>



<p>If you like this tutorial, you could <a href="https://buymeacoffee.com/tutolibro" data-type="link" data-id="https://buymeacoffee/tutolibro" target="_blank" rel="noreferrer noopener">buy me a coffee</a> to help me continue writing add-free tutorials.</p>



<p>Thank you!</p>



<div class="wp-block-group is-content-justification-space-between is-nowrap is-layout-flex wp-container-core-group-is-layout-0dfbf163 wp-block-group-is-layout-flex">

</div>
]]></content:encoded>
					
					<wfw:commentRss>https://tutolibro.org/2025/11/26/assign-your-python-macro-to-a-button-in-libreoffice/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1555</post-id>	</item>
		<item>
		<title>LibreOffice Calc &#038; Python Programming: Part 1 – Requirements</title>
		<link>https://tutolibro.org/2025/11/26/libreoffice-calc-python-programming-part-1-requirements/</link>
					<comments>https://tutolibro.org/2025/11/26/libreoffice-calc-python-programming-part-1-requirements/#respond</comments>
		
		<dc:creator><![CDATA[gweno]]></dc:creator>
		<pubDate>Wed, 26 Nov 2025 15:29:24 +0000</pubDate>
				<category><![CDATA[LibreOffice]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://tutolibro.org/?p=1570</guid>

					<description><![CDATA[I am finally starting to write this tutorial. Thanks for your patience, and thanks to Nukool for your comment, it really gave me motivation to write this course. In this Part 1 of LibreOffice Calc &#38; Python programming tutorial we...<br /><a class="read-more-button" href="https://tutolibro.org/2025/11/26/libreoffice-calc-python-programming-part-1-requirements/">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>I am finally starting to write this tutorial. Thanks for your patience, and thanks to Nukool for your comment, it really gave me motivation to write this course.</p>



<p>In this Part 1 of LibreOffice Calc &amp; Python programming tutorial we are looking at:</p>



<ul class="wp-block-list">
<li>some <strong><a href="#sofware">Software</a></strong> you need</li>



<li>the <strong><a href="#apso">APSO extension</a></strong> that&#8217;ll make things much easier</li>



<li>an <strong><a href="https://tutolibro.org/2019/07/26/libreoffice-calc-python-programming-part-1-requirements/">extra step for Linux</a></strong> users</li>



<li>useful <strong><a href="https://tutolibro.org/2019/07/26/libreoffice-calc-python-programming-part-1-requirements/">documentation</a></strong></li>



<li><strong><a href="https://tutolibro.org/2019/07/26/libreoffice-calc-python-programming-part-1-requirements/">further notes</a></strong></li>
</ul>



<h3 class="wp-block-heading" id="software">Software</h3>



<h4 class="wp-block-heading">LibreOffice</h4>



<p>You will of course need LibreOffice, you can download the <a href="https://www.libreoffice.org/">latest version here.</a><br>LibreOffice is normally shipped with a PyUNO bridge. This allows it to bind its components with the Python language. It also makes it possible to program LibreOffice with Python. (see at end of this article if you&#8217;re using a Linux ).</p>



<h4 class="wp-block-heading"><strong>Python</strong> 3</h4>



<p>You also need the Python 3 programming language on your computer.<br>It may be installed already. For now I let you do it yourself, but I might write a quick help later. Just web search for &#8216;python 3&#8217; for your Operating system. </p>



<h4 class="wp-block-heading"><strong>IDE / Text Editor</strong></h4>



<p>You will also need a text editor or even better an IDE (Integrated Development Environment) to write your python program. The advantage of an IDE versus a simple text editor is that it offers tools to organise your codes, an IDE can also makes it easier to spot errors and offers all sort of features to speed up and ease coding like word auto-completion, search and replace.<br>If you are a programmer you may already have a preference for a simple editor or a clever one. I am using a free open-source IDE called <a href="https://www.geany.org/"><strong>geany</strong></a>, but other popular ones are Eclipse, code::block and the famous Microsoft Visual Studio. They all have their pros and cons, here is <a href="https://pypl.github.io/IDE.html">the Top 20 of the most popular ones</a>. Geany is perfect for &#8216;small jobs&#8217; like we are going to do, but again it&#8217;s also fine to use a text editor like notepad.</p>



<h4 class="wp-block-heading">JRE install</h4>



<p id="apso">If your computer does not have Java Runtime Environment already you will need to install it through the Oracle website. You can also follow instruction <a href="https://java.com/en/download/manual.jsp">here</a>. JRE is indeed required to be able to use macros within LibreOffice.</p>



<h3 class="wp-block-heading"><strong>APSO extension</strong></h3>



<p>By default LibreOffice Python Macros are independent from any LibreOffice file. So to execute a python program within a LibreOffice Calc Spreadsheet for example you would need to go in Tools/Macro/Run Macro and select the python program from a list corresponding to a folder on your Hard drive. And this list, for example &#8216;MyMacro&#8217;, would be accessible for any LibreOffice file (Calc, Text, Base, etc&#8230;). This is great but not helpful when you want a particular python program to be used specifically for a particular file. <br>APSO is a LibreOffice extension that helps with organising Python Macros within your LibreOffice files. You just need to download <a href="https://extensions.libreoffice.org/extensions/apso-alternative-script-organizer-for-python">the APSO extension here</a> and then install the tool via Tools/Extensions Manager. One great advantage of APSO is its EditorKicker that you can set up to use your preferred text editor or IDE to edit your Python program.<br>One last note about using APSO, although the programs themselves are saved in the same folders than all other programs, the ones you choose to be embed in a particular file will be linked to that file, or rather for example LibreOffice calc file will have a link to the  python program in its parameters and you will be able to see your program attached to LibreOffice documents currently opened.</p>



<h3 class="wp-block-heading" id="linux"><strong>Extra step for linux</strong></h3>



<p>I had to do one extra step when I was using LibreOffice 5 under Linux mint Operating System: adding some library. Without it it was not possible to do any Python macros within LibreOffice. This is an easy step, just open a terminal, type and execute:</p>



<p>sudo apt-get install libreoffice-script-provider-python</p>



<p>It will be the same for Ubuntu. For other linux distro you will need to check yourself but it&#8217;d be similar using the in-house package manager.</p>



<h3 class="wp-block-heading" id="doc"><strong>Documentation</strong></h3>



<p>It is not easy to find helpful documentation for programming Python Macros for LibreOffice. Firstly it&#8217;s hard to find a site or forum that have real documentation about using Python for LibreOffice, and secondly the tasks explained are usually too complicated for a beginner. However this is the best place I found so far with a list of links to Python program examples. You will not that most of the examples are using a Python library created by &#8216;Danny&#8217;.</p>



<h3 class="wp-block-heading" id="notes"><strong>Further notes</strong></h3>



<p>In my tutorial we will create everything from scratch and develop simple and useful functions.<br>I still haven&#8217;t decided what topic to cover to illustrate this tutorial. I am hesitating between continuing the <a href="https://tutolibro.org/2018/05/02/tutorial-make-a-time-schedule-in-libreoffice-using-formulas-and-a-simple-macro/">time schedule</a>, starting invoice manager or a garden planner.<br>If you have any preference please let me know in your comment.<br></p>



<p>If you like this tutorial, you could <a href="https://buymeacoffee.com/tutolibro" data-type="link" data-id="https://buymeacoffee/tutolibro" target="_blank" rel="noreferrer noopener">buy me a coffee</a> to help me continue writing add-free tutorials.</p>



<p>Thank you!</p>



<div class="wp-block-group is-content-justification-space-between is-nowrap is-layout-flex wp-container-core-group-is-layout-0dfbf163 wp-block-group-is-layout-flex">

</div>
]]></content:encoded>
					
					<wfw:commentRss>https://tutolibro.org/2025/11/26/libreoffice-calc-python-programming-part-1-requirements/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1570</post-id>	</item>
		<item>
		<title>Embedding vs. Storing Python Macros in LibreOffice</title>
		<link>https://tutolibro.org/2025/11/19/embedding-vs-storing-python-macros-in-libreoffice/</link>
					<comments>https://tutolibro.org/2025/11/19/embedding-vs-storing-python-macros-in-libreoffice/#respond</comments>
		
		<dc:creator><![CDATA[gweno]]></dc:creator>
		<pubDate>Wed, 19 Nov 2025 23:22:50 +0000</pubDate>
				<category><![CDATA[Calc]]></category>
		<category><![CDATA[LibreOffice]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[calc]]></category>
		<category><![CDATA[hello world]]></category>
		<category><![CDATA[libreoffice]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">https://tutolibro.org/?p=1580</guid>

					<description><![CDATA[This article helps you decide whether to embed your python macro in the file. It also explores saving it in a macro repository. With the APSO add-on (see previous article) you can embed your macro within the LibreOffice File. This...<br /><a class="read-more-button" href="https://tutolibro.org/2025/11/19/embedding-vs-storing-python-macros-in-libreoffice/">Read more</a>]]></description>
										<content:encoded><![CDATA[
<ul class="wp-block-list">
<li></li>
</ul>



<p>This article helps you decide whether to embed your python macro in the file. It also explores saving it in a macro repository.</p>



<p>With the APSO add-on (<a href="https://tutolibro.org/2019/07/26/getting-started-with-libreoffice-calc-and-python/" data-type="post" data-id="563">see previous article</a>) you can embed your macro within the LibreOffice File. This can be useful for example when you want to send your LibreOffice file with the Python Macro. A downside is that the Python macro will not be accessible outside of the LibreOffice file you sent. So you will need to open the LibreOffice file. Then open the Python Macro organiser. This is necessary to edit the Python program.</p>



<p>There are alternatives to embedding the Python program. You can place it in an organized directory while still using APSO. This lets you re-use it for any other LibreOffice document. You can also edit the program without opening the LibreOffice document if you open it from the relevant folder. If you want to send your LibreOffice Document to someone, there is a trade-off. You will also need to send the Python macro.</p>



<p>I am in favor of keeping programs in a tidy manner. This approach allows me to re-use them across many different files. But the choice is entirely up to you. I hope </p>



<p>To illustrate these 2 cases, let&#8217;s have a look at an example:</p>



<p>I have a file called &#8220;<strong>HelloWorld.ods</strong>&#8221; and two Python files: the first one is called &#8220;<strong>HelloWorld.py</strong>&#8221; and the other file is called &#8220;<strong>Testing.py&#8221;</strong>. The first python file is embedded in the LibreOffice file, the second is in the shared Python Scripts directory.</p>



<p class="has-text-align-left">In the first case scenario, after opening HelloWorld.ods, I can go to the Python Script Organizer, in Tools&gt;Macro&gt;Organize Python Scripts (shortcut Alt+Shift+F11) from the APSO extension. Alternatively I can use the LibreOffice Standard Macro Organiser in Tools&gt;Macro&gt;Organise Macros&gt;Python&#8230;.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="543" height="672" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc01.png" alt="" class="wp-image-848" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc01.png 543w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc01-242x300.png 242w" sizes="auto, (max-width: 543px) 100vw, 543px" /></figure>



<p class="has-text-align-left"><br>In the Python Scripts Organiser you will see that your Python Macro is listed within the LibreOffice File&#8217;s name.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="302" height="311" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc02.png" alt="" class="wp-image-849" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc02.png 302w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc02-291x300.png 291w" sizes="auto, (max-width: 302px) 100vw, 302px" /><figcaption class="wp-element-caption">Python Macro HelloWorld is within the calc document.</figcaption></figure>



<p><br>When you choose to edit the Python Macro, select &#8216;Menu&gt;Edit&#8217; from the &#8216;Python scripts&#8217; window. The edited file&#8217;s path is temporary. It is only used for the time of editing this Python program.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="646" height="182" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc03.png" alt="" class="wp-image-850" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc03.png 646w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc03-300x85.png 300w" sizes="auto, (max-width: 646px) 100vw, 646px" /></figure>



<p>So where is the Python Script saved on your hard drive?<br>As I wrote earlier, it&#8217;s embedded in the LibreOffice File. If you don&#8217;t believe me, here is a trick to find out:<br>If I rename my &#8216;HelloWorld.ods&#8217; in &#8216;HelloWorld.zip&#8217;. I can then unzip it to see the archived compressed files and folders that constitute the LibreOffice file itself(with e.g. Archive Manager on Linux, winzip on Windows, or Archive Utility on Mac). In the list of folders, I spot a folder called &#8216;Scripts&#8217;. Then, I find a sub-folder called &#8216;python&#8217;. OH SURPRISE! The python script is there!</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="424" height="355" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc04.png" alt="" class="wp-image-851" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc04.png 424w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc04-300x251.png 300w" sizes="auto, (max-width: 424px) 100vw, 424px" /></figure>



<p> If you want to do that too, when you&#8217;re done don&#8217;t forget to rename the file back with its &#8216;.ods&#8217; extension.</p>



<p>In the second case scenario,we are saving our Python script our Python script &#8216;Testing.py&#8217; is not listed in the Macro manager within the LibreOffice File, but this time I created it as part of my Library &#8216;MyPythonLibrary&#8217; within another Library called &#8216;Tutorial&#8217;.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="362" height="373" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc00.png" alt="" class="wp-image-847" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc00.png 362w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc00-291x300.png 291w" sizes="auto, (max-width: 362px) 100vw, 362px" /><figcaption class="wp-element-caption">&#8216;main&#8217; is the Python function that is in the File &#8216;Testing.py&#8217;.</figcaption></figure>



<p>And this time if I edit &#8216;Testing&#8217;, I can see the path is not a temporary one. I can access it even when LibreOffice is closed.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="685" height="282" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc05.png" alt="" class="wp-image-852" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc05.png 685w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc05-300x124.png 300w" sizes="auto, (max-width: 685px) 100vw, 685px" /></figure>



<p>In fact your Python programs can be directly accessed on your computer at the following location:<br><span style="text-decoration: underline;">For Linux: </span><br>/home/&lt;user name&gt;/.config/libreoffice/4/user/Scripts/python<br>(to see folder &#8216;.config&#8217; you need to &#8216;Show hidden files&#8217; , the shortcut CTRL+h).<br><span style="text-decoration: underline;">For Windows:</span><br>C:\Users\&lt;user_name&gt;\AppData\Roaming\LibreOffice\4\Scripts\python<br><span style="text-decoration: underline;">For Mac:</span><br>(I think it&#8217;s)/Users/&lt;user name&gt;/Library/Application Support/LibreOffice/4/user\Scripts\python<br>(Please let me know in a comment if you know for sure what the folder is for Mac OS).</p>



<h4 class="wp-block-heading">Time for your First LibreOffice line of code!</h4>



<p>I know you can&#8217;t wait anymore! So let&#8217;s create our first program in Python in a LibreOffice Calc Document in <a href="https://tutolibro.org/2025/11/03/write-hello-world-in-libreoffice-calc-using-python/" data-type="post" data-id="1533">this next post</a>.</p>



<p>If you like this tutorial, you could <a href="https://buymeacoffee.com/tutolibro" data-type="link" data-id="https://buymeacoffee/tutolibro" target="_blank" rel="noreferrer noopener">buy me a coffee</a> to help me continue writing add-free tutorials.</p>



<p>Thank you!</p>



<div class="wp-block-group is-content-justification-space-between is-nowrap is-layout-flex wp-container-core-group-is-layout-0dfbf163 wp-block-group-is-layout-flex">

</div>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://tutolibro.org/2025/11/19/embedding-vs-storing-python-macros-in-libreoffice/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1580</post-id>	</item>
		<item>
		<title>Write &#8216;Hello World!&#8221; in LibreOffice Calc using Python</title>
		<link>https://tutolibro.org/2025/11/03/write-hello-world-in-libreoffice-calc-using-python/</link>
					<comments>https://tutolibro.org/2025/11/03/write-hello-world-in-libreoffice-calc-using-python/#respond</comments>
		
		<dc:creator><![CDATA[gweno]]></dc:creator>
		<pubDate>Mon, 03 Nov 2025 23:00:40 +0000</pubDate>
				<category><![CDATA[Calc]]></category>
		<category><![CDATA[LibreOffice]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[hello world]]></category>
		<category><![CDATA[libreoffice]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">https://tutolibro.org/?p=1533</guid>

					<description><![CDATA[First let&#8217;s get the coding done, then we&#8217;ll dive in to it. You can either copy this block of code above or better type it yourself. Typing the code yourself will take longer but it&#8217;s the best way to remember...<br /><a class="read-more-button" href="https://tutolibro.org/2025/11/03/write-hello-world-in-libreoffice-calc-using-python/">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>First let&#8217;s get the coding done, then we&#8217;ll dive in to it.</p>



<pre class="wp-block-code"><code># Created by Gweno 16/08/2019 for tutolibro.org
# This program displays 'Hello World!" in cell A1 of the 
# current Calc document.

# get the doc from the scripting context 
# which is made available to all scripts
desktop = XSCRIPTCONTEXT.getDesktop()
model = desktop.getCurrentComponent()

def HelloWorld():
    """Write 'Hello World!' in Cell A1"""

    # access the active sheet
    active_sheet = model.CurrentController.ActiveSheet

    # write 'Hello World' in A1
    active_sheet.getCellRangeByName("A1").String = "Hello World!"
</code></pre>



<p>You can either copy this block of code above or better type it yourself. Typing the code yourself will take longer but it&#8217;s the best way to remember a new language.</p>



<p>The first lines starting with &#8216;#&#8217; are comments. <br>A comment in a program is a line that is not processed when the program is executed. It helps the person reading the program to understand what the code is doing. Most of the time, this person is yourself. Comments will help you remember what you were trying to achieve with this code.</p>



<p>The blank space at the start of indented lines should be made of 4 spaces:<br><code>&nbsp;&nbsp;&nbsp;&nbsp;active_sheet = model.CurrentController.ActiveSheet</code></p>



<p>If you don&#8217;t do that it will create an error because the Python interpreter will not recognise the line as being part of the function define by:<br><code>def HelloWorld():</code></p>



<p>The instruction &#8216;def&#8217; is to &#8216;define a function&#8217;. A function is a set of written instructions. It can be run on its own. It can also be &#8216;called&#8217; by other functions to be executed.<br>Our function here is called &#8216;HelloWorld&#8217;. The part between parenthesis &#8216;()&#8217; is where you write the arguments to be used by the function. In our case we are not &#8216;passing&#8217; any argument to the function &#8216;HelloWorld&#8217; for now. That&#8217;s why we have nothing within the parenthesis &#8216;()&#8217;.<br>If you want to assign this macro to a button, you need to pass a specific argument. This argument is necessary for the macro to work when pressing the button. (see <a href="https://tutolibro.org/2025/10/27/libreoffice-calc-python-programming-part-2-hello-world/" data-type="post" data-id="578">this post</a> explains how to assign a button to a python macro)</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="590" height="384" src="https://tutolibro.org/wp-content/uploads/2025/11/HelloWorldCalc.png" alt="" class="wp-image-1540" srcset="https://tutolibro.org/wp-content/uploads/2025/11/HelloWorldCalc.png 590w, https://tutolibro.org/wp-content/uploads/2025/11/HelloWorldCalc-300x195.png 300w" sizes="auto, (max-width: 590px) 100vw, 590px" /></figure>



<p><strong><span style="text-decoration: underline;">Explanations:</span></strong><br><strong>Lines 1,2,3,5,6: </strong>these lines start with a &#8216;#&#8217; so they are comments.<br><strong>Lines 4,9,18:</strong> these empty lines are only for making the program easier to read. They serve to separate the different sets of instructions within the program. The Python interpreter does not need them but these empty lines make the code more readable for us.</p>



<p><strong>Line 7:</strong><br><code>desktop = <a href="https://tutolibro.tech/2022/11/14/what-is-xscriptcontext/" data-type="post" data-id="1149">XSCRIPTCONTEXT</a>.<a type="post" href="https://tutolibro.org/2023/02/08/what-is-getdesktop/" id="1157">getDesktop</a>()</code><br>This line is what allows us to use Python language to manipulate LibreOffice&#8217;s components. It is a bit complicated to explain exactly what this line does. In short, we define &#8216;desktop&#8217; to hold the &#8216;<code><a href="https://tutolibro.tech/2022/11/14/what-is-xscriptcontext/" data-type="post" data-id="1149">XSCRIPTCONTEXT</a></code>&#8216; interface provided by LibreOffice for our scripts (programs). The &#8216;<a type="post" href="https://tutolibro.org/2023/02/08/what-is-getdesktop/" id="1157">getDesktop</a>()&#8217; function is used to obtain a reference for our scripts to operate on. (It is not a reference to a computer desktop!). (Click on the links above to read more in my &#8216;bitesize&#8217; section).</p>



<p><strong>Line 8:</strong><br><code>model = desktop.getCurrentComponent()</code><br>Here, we define &#8216;model&#8217; to be the current component of &#8216;desktop&#8217;. Thus, we are referencing the current document open. It should be a Calc document<strong>.</strong></p>



<p><strong>Line 10:</strong><br><code>def HelloWorld():</code> <br>Define a new function called &#8216;HelloWorld&#8217; that has no arguments.<br>The &#8216;:&#8217; at the end is essential, it&#8217;s to say that what is following is the actual code written for this function. And every line that follow this function&#8217;s 1st line should start with 4 spaces.<br>The function finishes when there is no lines after it. Or when the next non empty line is not a comment and starts with no space.<br><strong>Line 11:</strong><br>      &#8220;&#8221;&#8221;Write &#8216;Hello World!&#8217; in Cell A1&#8243;&#8221;&#8221;<br>This line is simply a description of the function. Also called a Docstring (DocStrings is short for Documentation Strings), it starts and ends with 3 quotation marks. It is not really useful for us right now. Still, it is good practice to have a short description for each of your functions. It&#8217;s different from a comment because this description can be displayed outside of the program as a &#8216;help&#8217; note.<br>To display docstrings, you can use the built-in function &#8216;help&#8217;, like illustrated in the APSO console below:</p>



<p><img loading="lazy" decoding="async" width="450" height="202" class="wp-image-1541" style="width: 450px;" src="https://tutolibro.org/wp-content/uploads/2025/11/help_helloworld.png" alt="Help function to display Docstring of HelloWorld.py" srcset="https://tutolibro.org/wp-content/uploads/2025/11/help_helloworld.png 354w, https://tutolibro.org/wp-content/uploads/2025/11/help_helloworld-300x135.png 300w" sizes="auto, (max-width: 450px) 100vw, 450px" /><br><strong><br>Line 14:</strong><br><code>&nbsp;&nbsp;&nbsp;&nbsp;active_sheet = model.CurrentController.ActiveSheet</code><br>Here we are defining &#8216;active_sheet&#8217; to be the current spreadsheet you are looking at.<br><strong>Line 17:</strong><br><code>&nbsp;&nbsp;&nbsp;&nbsp;active_sheet.getCellRangeByName("A1").String = "Hello World!"</code><br>Finally! Now we have a reference to the current LibreOffice Context. We have the current LibreOffice Calc Document (component) and the current spreadsheet. Therefore, we can access the cell &#8216;A1&#8217;. We can then assign to its &#8216;String&#8217; parameter the text &#8220;Hello World!</p>



<p><strong><span style="text-decoration: underline;">Exercise:</span></strong><br>Add to function HelloWorld a line of code to display &#8220;Bye Bye World!&#8221; in cell &#8216;B2&#8217;. I am sure you can handle that!</p>



<p>If you like this tutorial, you could <a href="https://buymeacoffee.com/tutolibro" data-type="link" data-id="https://buymeacoffee/tutolibro" target="_blank" rel="noreferrer noopener">buy me a coffee</a> to help me continue writing add-free tutorials.</p>



<p>Thank you!</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://tutolibro.org/2025/11/03/write-hello-world-in-libreoffice-calc-using-python/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1533</post-id>	</item>
		<item>
		<title>LibreOffice Calc &#038; Python Programming: Part 2 – Hello World</title>
		<link>https://tutolibro.org/2025/10/27/libreoffice-calc-python-programming-part-2-hello-world/</link>
					<comments>https://tutolibro.org/2025/10/27/libreoffice-calc-python-programming-part-2-hello-world/#comments</comments>
		
		<dc:creator><![CDATA[gweno]]></dc:creator>
		<pubDate>Mon, 27 Oct 2025 00:32:47 +0000</pubDate>
				<category><![CDATA[Calc]]></category>
		<category><![CDATA[LibreOffice]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[calc]]></category>
		<category><![CDATA[hello world]]></category>
		<category><![CDATA[libreoffice]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">http://superbusydaddy.com/?p=578</guid>

					<description><![CDATA[In this episode of my LibreOffice Calc &#38; Python Programming tutorial, we are going to write our first Python Macro. It will write &#8216;Hello World&#8217; in cell A1 of a LibreOffice Calc document. How exciting is that!?! Here is the...<br /><a class="read-more-button" href="https://tutolibro.org/2025/10/27/libreoffice-calc-python-programming-part-2-hello-world/">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p id="top">In this episode of my LibreOffice Calc &amp; Python Programming tutorial, we are going to write our first Python Macro. It will write &#8216;Hello World&#8217; in cell A1 of a LibreOffice Calc document. How exciting is that!?!</p>



<p>Here is the plan for this part 2 of the tutorial:</p>



<ul class="wp-block-list">
<li><a href="#workflow">Get your workflow</a> right: deciding between your macro embedded in the file or saved in a macro repository.</li>



<li><a href="#code">First line of code</a> and writing &#8220;Hello World!&#8221; in Cell A1.</li>



<li id="workflow">Assigning the macro to a LibreOffice <a href="#button">Control Button</a>.</li>
</ul>



<h4 class="wp-block-heading">Get your workflow right                                                                                                                 (<a href="#top">Back to top</a>)</h4>



<p>With the APSO add-on (<a href="https://tutolibro.org/2019/07/26/libreoffice-calc-python-programming-part-1-requirements/">see previous article</a>) you can embed your macro within the LibreOffice File. This can be useful when you want to send your file with the Python Macro. One downside if you do that is that the Python macro is not accessible outside of the LibreOffice file. So you&#8217;ll need to open the LibreOffice file and open the Python Macro organiser in order to edit the Python program. There are alternatives to embedding the Python program. You can place it in an organized directory while still using APSO. This allows you to re-use it for any other LibreOffice document. You can also edit the program without opening the LibreOffice document if you open it from the relevant folder. If you want to send your LibreOffice Document to someone, there is a trade-off. You will also need to send the Python macro.</p>



<p>I am in favor of keeping my programs in a tidy manner. This approach allows me to re-use them across many different files. However, the choice is entirely up to you.</p>



<p>To illustrate these 2 cases, let&#8217;s have a look at an example:</p>



<p>I have a file called &#8220;<strong>HelloWorld.ods</strong>&#8221; and two Python files: the first one is called &#8220;<strong>HelloWorld.py</strong>&#8221; and the other file is called &#8220;<strong>Testing.py&#8221;</strong>. The first python file is embedded in the LibreOffice file, the second is in the shared Python Scripts directory.</p>



<p class="has-text-align-left">In the first case scenario, after opening HelloWorld.ods, I can go to the Python Script Organizer, in Tools&gt;Macro&gt;Organize Python Scripts (shortcut Alt+Shift+F11) from the APSO extension. Alternatively I can use the LibreOffice Standard Macro Organiser in Tools&gt;Macro&gt;Organise Macros&gt;Python&#8230;.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="543" height="672" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc01.png" alt="" class="wp-image-848" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc01.png 543w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc01-242x300.png 242w" sizes="auto, (max-width: 543px) 100vw, 543px" /></figure>



<p class="has-text-align-left"><br>In the Python Scripts Organiser you will see that your Python Macro is listed within the LibreOffice File&#8217;s name.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="302" height="311" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc02.png" alt="" class="wp-image-849" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc02.png 302w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc02-291x300.png 291w" sizes="auto, (max-width: 302px) 100vw, 302px" /><figcaption class="wp-element-caption">Python Macro HelloWorld is within the calc document.</figcaption></figure>



<p><br>When you choose to edit the Python Macro, select &#8216;Menu&gt;Edit&#8217; from the &#8216;Python scripts&#8217; window. The edited file&#8217;s path is temporary. It is only used for the time of editing this Python program.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="646" height="182" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc03.png" alt="" class="wp-image-850" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc03.png 646w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc03-300x85.png 300w" sizes="auto, (max-width: 646px) 100vw, 646px" /></figure>



<p>So where is the Python Script saved on your hard drive?<br>As I wrote earlier, it&#8217;s embedded in the LibreOffice File. If you don&#8217;t believe me, here is a trick to find out:<br>If I rename my &#8216;HelloWorld.ods&#8217; in &#8216;HelloWorld.zip&#8217; I can then unzip it to see the archived compressed files and folders that constitute the LibreOffice file itself (with  e.g. Archive Manager on Linux, winzip on Windows, or Archive Utility on Mac). In the list of folders I can then spot a folder called &#8216;Scripts&#8217;, then a sub-folder called &#8216;python&#8217;, and OH SURPRISE! the python script is there!</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="424" height="355" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc04.png" alt="" class="wp-image-851" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc04.png 424w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc04-300x251.png 300w" sizes="auto, (max-width: 424px) 100vw, 424px" /></figure>



<p> If you want to do that too, when you&#8217;re done don&#8217;t forget to rename the file back with its &#8216;.ods&#8217; extension.</p>



<p>In the second case scenario,we are saving our Python script our Python script &#8216;Testing.py&#8217; is not listed in the Macro manager within the LibreOffice File, but this time I created it as part of my Library &#8216;MyPythonLibrary&#8217; within another Library called &#8216;Tutorial&#8217;.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="362" height="373" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc00.png" alt="" class="wp-image-847" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc00.png 362w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc00-291x300.png 291w" sizes="auto, (max-width: 362px) 100vw, 362px" /><figcaption class="wp-element-caption">&#8216;main&#8217; is the Python function that is in the File &#8216;Testing.py&#8217;.</figcaption></figure>



<p>And this time if I edit &#8216;Testing&#8217;, I can see the path is not a temporary one and I can access it even when LibreOffice is closed.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="685" height="282" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc05.png" alt="" class="wp-image-852" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc05.png 685w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc05-300x124.png 300w" sizes="auto, (max-width: 685px) 100vw, 685px" /></figure>



<p id="code">In fact your Python programs can be directly accessed on your computer at the following location:<br><span style="text-decoration: underline;">For Linux: </span><br>/home/&lt;user name&gt;/.config/libreoffice/4/user/Scripts/python<br>(to see folder &#8216;.config&#8217; you need to &#8216;Show hidden files&#8217; , the shortcut CTRL+h).<br><span style="text-decoration: underline;">For Windows:</span><br>C:\Users\&lt;user_name&gt;\AppData\Roaming\LibreOffice\4\Scripts\python<br><span style="text-decoration: underline;">For Mac:</span><br>(I think it&#8217;s)/Users/&lt;user name&gt;/Library/Application Support/LibreOffice/4/user\Scripts\python<br>(Please let me know in a comment if you know for sure what the folder is for Mac OS).</p>



<h4 class="wp-block-heading">First line of code!                                                                                                                 (<a href="#top">Back to top</a>)</h4>



<p>I know you can&#8217;t wait anymore! So let&#8217;s write our first line of code in Python, within a LibreOffice Calc Document.</p>



<p>So after creating a new Calc document, go in the Macro manager (if you have installed the APSO extension: ALT+Shift+F11), then as explained earlier in this lesson you can have your program either in calc document or in a library outside the document. To do so, choose between &#8216;My Macros&#8217;, &#8216;LibreOffice Macros&#8217; or the name of the document itself.<br>I do prefer saving my python macros in the &#8216;My Macros&#8217; Library.<br>You can also create sub-folders, called  libraries, or directly create your program by choosing &#8216;Create Module&#8217; in the &#8216;Menu&#8217;.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="339" height="335" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc06.png" alt="" class="wp-image-853" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc06.png 339w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc06-300x296.png 300w" sizes="auto, (max-width: 339px) 100vw, 339px" /></figure>



<p>So go ahead and create a Module, name it &#8220;HelloWorld&#8221;, then once the module is listed and selected, click again on &#8216;Menu&#8217; and choose &#8216;edit&#8217;.</p>



<p>And then you get either a default editor or the one you have linked with APSO to pop up with a new program that content nothing but a couple of lines like these:</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="427" height="76" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc07.png" alt="" class="wp-image-854" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc07.png 427w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc07-300x53.png 300w" sizes="auto, (max-width: 427px) 100vw, 427px" /></figure>



<p>The first line is a comment.<br>A comment in a program is a line that is not processed when the program is executed. So it&#8217;s not a line of code, it is usually to help the person who is going to read your program (most of the time, yourself) to understand what the following code is aiming to do.<br>So to write comments in your Python programs simply add a &#8216;#&#8217; at the start of the line.<br>Don&#8217;t worry about the second line, in fact you can delete these two lines for now.<br>Instead you could like me write your name, the date and what the program is for:</p>



<p><code># Created by Gweno 16/08/2019 for tutolibro.tech<br># This program displays 'Hello World!" in cell A1 of the</code><br><code># current Calc document.</code></p>



<p>Then Finally here is the code for writing &#8220;Hello World!&#8221; in cell A1:</p>



<hr class="wp-block-separator has-css-opacity"/>



<pre class="wp-block-code"><code># Created by Gweno 16/08/2019 for tutolibro.tech
# This program displays 'Hello World!" in cell A1 of the 
# current Calc document.

def HelloWorld():
    """Write 'Hello World!' in Cell A1"""

# get the doc from the scripting context
# which is made available to all scripts
    desktop = XSCRIPTCONTEXT.getDesktop()
    model = desktop.getCurrentComponent()

# access the active sheet
    active_sheet = model.CurrentController.ActiveSheet

# write 'Hello World' in A1
    active_sheet.getCellRangeByName("A1").String = "Hello World!"
</code></pre>



<hr class="wp-block-separator has-css-opacity"/>



<p>You can either copy this block of code above or better type it manually yourself. Typing the code yourself will take longer but it&#8217;s the best way to remember a new language.<br>When you type it make sure that you leave 4 empty spaces to indent the lines that are not starting at the beginning of their lines, like:<br><code>    desktop = XSCRIPTCONTEXT.getDesktop()</code><br>If you don&#8217;t do that it will create an error because the Python interpreter will not recognise the line as part of the function define by:<br><code>def HelloWorld():</code><br>So the instruction &#8216;def&#8217; is to &#8216;define a function&#8217;. A function is a set of written instructions that can be run on its own or &#8216;called&#8217; by other functions to be executed.<br>Our function here is called &#8216;HelloWorld&#8217; and the part between parenthesis &#8216;()&#8217; is where you write the arguments to be used by the function. In our case we are not &#8216;passing&#8217; any argument to the function &#8216;HelloWorld&#8217; for now, that is why we have nothing within the parenthesis &#8216;()&#8217;.<br>You need to know that when we will assign our macro to a button we will need to pass a specific argument for our macro to work when we press the button.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="605" height="332" src="https://tutolibro.org/wp-content/uploads/2023/11/lopy-helloworld.png" alt="" class="wp-image-1202" srcset="https://tutolibro.org/wp-content/uploads/2023/11/lopy-helloworld.png 605w, https://tutolibro.org/wp-content/uploads/2023/11/lopy-helloworld-300x165.png 300w" sizes="auto, (max-width: 605px) 100vw, 605px" /></figure>



<p><strong><span style="text-decoration: underline;">Explanations:</span></strong><br><strong>Lines 1,2,3,8,9,13,16: </strong>these lines start with a &#8216;#&#8217; so they are comments.<br><strong>Lines 4,7,12,15,18:</strong> these empty lines are only for making the program easier to read,by separating the different set of instructions within the program. The Python interpreter does not need them but these empty lines make the code more readable for us.<br><strong>Line 5:</strong><br><code>def HelloWorld():</code> <br>Define a new function called &#8216;HelloWorld&#8217; that has no arguments.<br>The &#8216;:&#8217; at the end is essential, it&#8217;s to say that what is following is the actual code written for this function. And every line that follow this function&#8217;s 1st line should start with 4 spaces.<br>The function finishes when either there is nothing after, or when a new line starts from the beginning with no space to start with (excluding comment lines).<br><strong>Line 6:</strong><br><code>   """Write 'Hello World!' in Cell A1"""</code><br>This line is simply a description of the function, it starts and ends with 3 quotation marks. It is not really useful for us right now but it is a good practice to have a short description for each of your function. It&#8217;s different from a comment because this description can be displayed from outside of the program as a &#8216;help&#8217; note.<br><strong>Line 10:</strong><br><code>    desktop = <a href="https://tutolibro.tech/2022/11/14/what-is-xscriptcontext/" data-type="post" data-id="1149">XSCRIPTCONTEXT</a>.<a href="https://tutolibro.org/2023/02/08/what-is-getdesktop/" type="post" id="1157">getDesktop</a>()</code><br>This line is what allows us to use Python language to manipulate LibreOffice&#8217;s components. It is a bit complicated to explained exactly what this line does but in short:<br>We define &#8216;desktop&#8217; to hold the &#8216;<code><a href="https://tutolibro.tech/2022/11/14/what-is-xscriptcontext/" data-type="post" data-id="1149">XSCRIPTCONTEXT</a></code>&#8216; interface provided by LibreOffice for our scripts (programs). The &#8216;<a href="https://tutolibro.org/2023/02/08/what-is-getdesktop/" type="post" id="1157">getDesktop</a>()&#8217; function is used to obtain a reference for our scripts to operate on. (It is not a reference to a computer desktop!). (Click on the links above to read more in my &#8216;bitesize&#8217; section)<br><strong>Line 11:</strong><br><code>    model = desktop.getCurrentComponent()</code><br>In the same way we define here &#8216;model&#8217; to be the current component of &#8216;desktop&#8217;, so effectively we are referencing to the current document open, which should be a Calc document<strong>.<br>Line 14:</strong><br><code>    active_sheet = model.CurrentController.ActiveSheet</code><br>Here we are defining &#8216;active_sheet&#8217;  to be the current spreadsheet you are looking at.<br><strong>Line 17:</strong><br><code>    active_sheet.getCellRangeByName("A1").String = "Hello World!"</code><br>Finally! Now that we have a reference to the current LibreOffice Context, the current LibreOffice Calc Document (component) and the current spreadsheet, we can access the cell &#8216;A1&#8217; from that current spreadsheet and assign to its &#8216;String&#8217; parameter the text &#8220;Hello World!&#8221;.</p>



<p id="button"><strong><span style="text-decoration: underline;">Exercise:</span></strong><br>Add to function HelloWorld a line of code to display &#8220;Bye Bye World!&#8221; in cell &#8216;B2&#8217;. I am sure you can handle that!</p>



<h4 class="wp-block-heading">Assign the macro to a LibreOffice Control Button.                                                                    (<a href="#top">Back to top</a>)</h4>



<p>You will quickly realise when you write a macro within libreOffice that it&#8217;s not really convenient to execute them through the Macro Manager because you need to access that menu and it takes a few clicks to do so (Quickest way to access the APSO Macro manager being [Alt] + [Shift] + [F11]). It is easy to create a button on your spreadsheet and to assign it to your macro and then when you&#8217;ll click on that button it will execute the macro.<br>So first we&#8217;ll <strong>create a button</strong> on the spreadsheet then we&#8217;ll <strong>assign the python macro</strong> to this button.</p>



<p><strong><span style="text-decoration: underline;">Create a button</span></strong>:<br>Simply by clicking on Menu &#8216;<strong>Insert&gt;Form Controls&gt;Push Button&#8217;</strong>:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="430" height="711" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc10.png" alt="" class="wp-image-857" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc10.png 430w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc10-181x300.png 181w" sizes="auto, (max-width: 430px) 100vw, 430px" /></figure>



<p>Then once you have the little cross to insert the button, just click for upper left corner of the button, then hold and release where you want the bottom right corner of the button.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="124" height="84" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc11.png" alt="" class="wp-image-858"/></figure>



<p><strong><span style="text-decoration: underline;">Assign the python macro</span></strong><span style="text-decoration: underline;">:</span><br>Once you have the button displayed, right click on it and select &#8216;Control&#8230;&#8217;</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="241" height="373" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc12.png" alt="" class="wp-image-859" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc12.png 241w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc12-194x300.png 194w" sizes="auto, (max-width: 241px) 100vw, 241px" /><figcaption class="wp-element-caption">Select &#8216;Control&#8217; from the new Button contextual menu</figcaption></figure>



<p>Then in the window &#8216;Properties&#8217; select the &#8216;Events&#8217; tab, scroll down a bit to find in the list of events the one called &#8216;Mouse button pressed&#8217;. On the right of this &#8216;Mouse button pressed&#8217; entry click on the button &#8216;[&#8230;]&#8217;.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="564" height="430" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc13.png" alt="" class="wp-image-860" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc13.png 564w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc13-300x229.png 300w" sizes="auto, (max-width: 564px) 100vw, 564px" /></figure>



<p>A window named  &#8220;Assign Action&#8217; pops up, click on the button &#8216;[Macro]&#8217; on the right hand side of this window.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="592" height="373" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc14.png" alt="" class="wp-image-861" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc14.png 592w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc14-300x189.png 300w" sizes="auto, (max-width: 592px) 100vw, 592px" /><figcaption class="wp-element-caption">Assign a macro to a button</figcaption></figure>



<p>You should then get the &#8216;Macro Selector&#8217; with your Macro Libraries. Simply go to the library where your macro is saved and select the macro &#8216;HelloWorld&#8217;,then press &#8216;OK&#8217;.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="722" height="202" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc15-e1565986476973.png" alt="" class="wp-image-862" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc15-e1565986476973.png 722w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc15-e1565986476973-300x84.png 300w" sizes="auto, (max-width: 722px) 100vw, 722px" /><figcaption class="wp-element-caption">Select the macro from Macro Selector</figcaption></figure>



<p>Then &#8216;OK&#8217; again in &#8216;Assign Macro&#8217; window, than close the &#8216;Properties&#8217; window.<br>Last thing to do is to come out the &#8216;Design&#8217; mode to be able to click on the button, do that by going to &#8216;Tools&gt;Forms&gt;Design Mode&#8217;.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="461" height="541" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc17.png" alt="" class="wp-image-864" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc17.png 461w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc17-256x300.png 256w" sizes="auto, (max-width: 461px) 100vw, 461px" /><figcaption class="wp-element-caption">Set design mode off</figcaption></figure>



<p>And now when you click on the button&#8230; tada&#8230;<br>ERROR!</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="546" height="255" src="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc16.png" alt="" class="wp-image-863" srcset="https://tutolibro.org/wp-content/uploads/2019/08/pyCalc16.png 546w, https://tutolibro.org/wp-content/uploads/2019/08/pyCalc16-300x140.png 300w" sizes="auto, (max-width: 546px) 100vw, 546px" /><figcaption class="wp-element-caption">Error: missing argument</figcaption></figure>



<p>This is because to be able to work, the function HelloWorld need all information from LibreOffice Context in the form of an argument. So we need to pass the argument &#8216;*args&#8217; in our function HelloWorld. So in your code in line 5 instead of:<br><code>def HelloWorld():</code><br>You should have:<br><code>def HelloWorld(*args):</code><br>Save your program again and then when you press on the button the cell  A1 will display &#8216;Hello World!&#8217; !!!</p>



<p>So there is the final version of the macro:</p>



<hr class="wp-block-separator has-css-opacity"/>



<pre class="wp-block-code"><code># Created by Gweno 16/08/2019 for tutolibro.tech
# This program displays 'Hello World!" in cell A1 of the 
# current Calc document.

def HelloWorld(*args):
    """Write 'Hello World!' in Cell A1"""
    
# get the doc from the scripting context 
# which is made available to all scripts
    desktop = XSCRIPTCONTEXT.getDesktop()
    model = desktop.getCurrentComponent()
    
# access the active sheet
    active_sheet = model.CurrentController.ActiveSheet

# write 'Hello World' in A1
    active_sheet.getCellRangeByName("A1").String = "Hello World!"</code></pre>



<p>You can clone or download this code from gitHub <a href="https://github.com/Gweno/tutolibro.tech/tree/master/lopy/part2">here</a>.</p>



<hr class="wp-block-separator has-css-opacity"/>



<h3 class="wp-block-heading">Good luck! and leave a comment if you are having problem to have this macro to work.</h3>



<hr class="wp-block-separator has-alpha-channel-opacity is-style-default"/>



<p>If you like this tutorial, you could <a href="https://buymeacoffee.com/tutolibro" data-type="link" data-id="https://buymeacoffee/tutolibro" target="_blank" rel="noreferrer noopener">buy me a coffee</a> to help me continue writing add-free tutorials.</p>



<p>Thank you!</p>



<div class="wp-block-group is-content-justification-space-between is-nowrap is-layout-flex wp-container-core-group-is-layout-0dfbf163 wp-block-group-is-layout-flex">

</div>
]]></content:encoded>
					
					<wfw:commentRss>https://tutolibro.org/2025/10/27/libreoffice-calc-python-programming-part-2-hello-world/feed/</wfw:commentRss>
			<slash:comments>16</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">578</post-id>	</item>
		<item>
		<title>LibreOffice Calc &#038; Python: part 9 &#8211; Reverse the order of cells content from a cell range</title>
		<link>https://tutolibro.org/2021/05/07/python-libreoffice-reverse-the-order-of-cells-content-from-a-cell-range/</link>
					<comments>https://tutolibro.org/2021/05/07/python-libreoffice-reverse-the-order-of-cells-content-from-a-cell-range/#comments</comments>
		
		<dc:creator><![CDATA[gweno]]></dc:creator>
		<pubDate>Fri, 07 May 2021 18:27:08 +0000</pubDate>
				<category><![CDATA[Calc]]></category>
		<category><![CDATA[LibreOffice]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[calc]]></category>
		<category><![CDATA[cell type]]></category>
		<category><![CDATA[libreoffice]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[setDataArray]]></category>
		<guid isPermaLink="false">https://tutolibro.tech/?p=1070</guid>

					<description><![CDATA[Using the code created in part 8, in this part 9 we are going to manipulate the data with functions getDataArray, setDataArray and Python Tuples. In this first example we are going to reverse the order of data within a...<br /><a class="read-more-button" href="https://tutolibro.org/2021/05/07/python-libreoffice-reverse-the-order-of-cells-content-from-a-cell-range/">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>Using the code created in <a href="https://tutolibro.org/2020/07/10/libreoffice-calc-python-programming-part-7-from-cells-range-to-python-tuple/">part 8</a>, in this part 9 we are going to manipulate the data with functions getDataArray, setDataArray and Python Tuples. In this first example we are going to reverse the order of data within a cell range.</p>



<p class="has-small-font-size"><em>edit 30/09/2021: Thanks to karolus for pointing out a few mistakes and for suggesting improvements for this tutorial.</em></p>



<h4 class="wp-block-heading">Here is the plan for this tutorial:</h4>



<ul class="wp-block-list"><li><strong>Prepare your file</strong></li><li><strong>Some useful functions</strong></li><li><strong>How to increment a tuple</strong></li><li><strong>Try in the console</strong></li><li><strong>Increment tuple step by step</strong></li><li><strong>Use built-in functions &#8216;tuple&#8217; and &#8216;reversed&#8217; together</strong></li><li><strong>Full ReverseRange.py file</strong></li><li><strong>Walk through the code</strong></li><li><strong>Test the code</strong></li></ul>



<h4 class="wp-block-heading">Prepare your file</h4>



<p>We start with creating a new folder, I named mine &#8216;part 9&#8217;, in the python scripts folder for LibreOffice. Depending on your OS, it will be at a specific location in your user folder. Within that location you can organise your python scripts the way you want and each folder will be seen as a module within the LibreOffice Python Script manager.<br>This part 9 will re-use some of the code from <a href="https://tutolibro.org/2020/07/17/libreoffice-calc-python-programming-part-8-from-python-tuple-to-cells-range/">part 8</a>  (also available on <a rel="noreferrer noopener" href="https://github.com/Gweno/tutolibro.tech/tree/master/lopy/part8" target="_blank">my gitHub repository</a>).</p>



<p>I named the file for this tutorial  &#8216;ReverseRange.py&#8217;.</p>



<p>Check my tutorial <a href="https://tutolibro.org/2019/08/16/libreoffice-calc-python-programming-part-2-hello-world/">hello world</a> if you need help to get started with python scripts for LibreOffice.</p>



<p>I usually assign a button or a keyboard shortcut to the main() program of my new python file. This is explained in <a href="https://tutolibro.org/2020/03/11/libreoffice-calc-python-programming-annex-1-assign-a-python-macro-to-a-key/">tutorial Annex 1</a>.</p>



<p>If you are starting from <a href="https://tutolibro.org/2020/07/17/libreoffice-calc-python-programming-part-8-from-python-tuple-to-cells-range/">part 8</a> code,  I am not using a <strong>context()</strong> function anymore to define the global variable needed for pyUNO, but instead I declare them at the global scope straight away. This make things easier and avoid repeating calling context in every function that need the global variables.</p>



<p>So this code below:</p>



<pre class="wp-block-code"><code>def context():
    
    # set global variables for context
    
    global desktop
    global model
    global active_sheet
    
    # get the doc from the scripting context 
    # which is made available to all scripts
    desktop = XSCRIPTCONTEXT.getDesktop()
    model = desktop.getCurrentComponent()
    
    # access the active sheet
    active_sheet = model.CurrentController.ActiveSheet</code></pre>



<p><strong>Is replaced by:</strong></p>



<pre class="wp-block-code"><code># set global variables for context
    
# get the doc from the scripting context 
# which is made available to all scripts
desktop = XSCRIPTCONTEXT.getDesktop()
model = desktop.getCurrentComponent()

# access the active sheet
active_sheet = model.CurrentController.ActiveSheet</code></pre>



<h4 class="wp-block-heading">Some useful functions</h4>



<p>I also replaced the section that is calculating Cell addresses from the current Range selection, by a simpler function returning a new range with horizontal and vertical offset as arguments. These two arguments having a default value  of 0.</p>



<pre class="wp-block-code"><code>def getSelectionAddresses(horizontalOffset = 0 , verticalOffset = 0):
    # get the range of addresses from selection
    oSelection = model.getCurrentSelection()
    oArea = oSelection.getRangeAddress()
    return oArea.StartColumn + horizontalOffset, oArea.StartRow + verticalOffset, oArea.EndColumn + horizontalOffset, oArea.EndRow + verticalOffset</code></pre>



<p>This function returns a tuple(a list you cannot change, also called immutable, see further for more details) with 4 elements. You can indeed create a tuple without using parenthesis.<br>If you are not convinced, try this in a python console:</p>



<pre class="wp-block-code"><code>&gt;&gt;&gt; fruits = "oranges","bananas","apples"
&gt;&gt;&gt; fruits
('oranges', 'bananas', 'apples')
&gt;&gt;&gt; type(fruits)
&lt;class 'tuple'&gt;</code></pre>



<p><em>(Don&#8217;t type the  &#8216;&gt;&gt;&gt;&#8217;, it&#8217;s python key prompt!)</em></p>



<p>The python built-in method <strong>type()</strong> tells you that you have defined the object &#8216;<strong>fruits</strong>&#8216; as an instance of class &#8216;<strong>tuple</strong>&#8216;.</p>



<h4 class="wp-block-heading">How to increment a tuple</h4>



<p>A tuple in python is a special type of array of data to store any type of data. Once a tuple has been created you cannot change its elements individually. A common solution to build a tuple is to use a &#8216;<strong>for loop</strong>&#8216; and to recreate the entire tuple with the same name at each loop iteration. It will look exactly like incrementing a variable, with each loop&#8217;s iteration looking like this:</p>



<pre class="wp-block-code"><code>myTuple = myTuple + (newElement,)</code></pre>



<p>The comma at the end within the parenthesis is important, if you don&#8217;t have it, the (newElement) is not a tuple but just a single element of whatever the type of newElement is.</p>



<h4 class="wp-block-heading">Try in the console</h4>



<p>So let&#8217;s open an APSO console (see <a href="https://tutolibro.org/2019/07/26/libreoffice-calc-python-programming-part-1-requirements/">part 1</a> if you need help), or if any other python console  like the Python Idle, or even your terminal after starting python3.</p>



<p>Then in the python console of your choice just create two new tuples like this:</p>



<pre class="wp-block-code"><code>source = (1,2,3)
target = ()</code></pre>



<p>You can do a quick print of your two tuple if you want to make sure your 2 tuples are good:</p>



<pre class="wp-block-code"><code>&gt;&gt;&gt; source
(1, 2, 3)
&gt;&gt;&gt; target = ()
&gt;&gt;&gt; ()
()
&gt;&gt;&gt; type(target)
&lt;class 'tuple'&gt;</code></pre>



<pre class="wp-block-verse">Note: as you can see you can create an empty tuple simply with empty parenthesis.</pre>



<h4 class="wp-block-heading">Increment tuple step by step</h4>



<p>To have our &#8216;<strong>target</strong>&#8216; tuple elements in the exact reverse order than the elements from the &#8216;<strong>source</strong>&#8216; tuple we need to do the following steps:</p>



<ol class="wp-block-list"><li>define target tuple equal to target tuple (which is empty at this step) + last element of source tuple (3)</li><li>define target tuple equal to target tuple(as it is) + second last element of source tuple (2)</li><li>define target tuple equal to target tuple(as it is) + first element of source tuple (1)</li></ol>



<p>In the console, it looks like this:</p>



<pre class="wp-block-code"><code>&gt;&gt;&gt; target = target + (source&#91;-1],)
&gt;&gt;&gt; target
(3,)
&gt;&gt;&gt; target = target + (source&#91;-2],)
&gt;&gt;&gt; target
(3, 2)
&gt;&gt;&gt; target = target + (source&#91;-3],)
&gt;&gt;&gt; target
(3, 2, 1)</code></pre>



<h4 class="wp-block-heading">Use the reversed() function</h4>



<p>Using a for loop and the <strong>reversed()</strong> function, we can now define a new function that takes a a tuple as argument and returns the reversed tuple, I called mine <strong>reverseTuple()</strong>:</p>



<pre class="wp-block-code"><code>def reverseTuple(aTuple):
    oReversedSource = ()
    for t in reversed(aTuple): 
        oReversedSource = oReversedSource + (t,)
    return oReversedSource</code></pre>



<h4 class="wp-block-heading">Use built-in functions &#8216;tuple()&#8217; and &#8216;reversed()&#8217; together.</h4>



<p>A nicer and more &#8216;pythonic&#8217; way of doing it, is to use the function <strong>tuple()</strong> and building the elements using what is called &#8216;tuple comprehension&#8217; with a loop on the reversed source tuple. This is done in one line only. So in the console it would look like this:</p>



<pre class="wp-block-code"><code>&gt;&gt;&gt; source = (1,2,3)
&gt;&gt;&gt; target = tuple(reversed(source))
&gt;&gt;&gt; target
(3, 2, 1)
&gt;&gt;&gt; </code></pre>



<p>So let&#8217;s create a <strong>reverse</strong> function. Now we have two functions doing the same job, just to show you that most of the time there are many ways to do the same thing in python and in programming in general. What counts is how readable the code is for you and other people that will read your code. </p>



<pre class="wp-block-code"><code>def reverse(aTuple):
    return tuple(reversed(aTuple))</code></pre>



<pre class="wp-block-verse">Note that you could do without this function and use the tuple comprehension directly where you need to reverse your tuple.</pre>



<p>For our final code we&#8217;ll keep the <strong>reverse</strong> function instead of the <strong>ReverseTuple</strong>, it&#8217;ll make people reading your code thinking, &#8220;That person knows python!&#8221;.</p>



<p>Now that we know how to reverse a tuple with python, we can apply it to a selected range of data within LibreOffice Calc.</p>



<h4 class="wp-block-heading">Full ReverseRange.py file</h4>



<pre class="wp-block-code"><code># Created by Gwenole Capp 05/05/2021
# For tutolibro.tech
# Public Domain, feel free to copy, modify, use in your own scripts
# 
# email: gwenole.capp@gmail.com
   
# set global variables for context
    
# get the doc from the scripting context 
# which is made available to all scripts
desktop = XSCRIPTCONTEXT.getDesktop()
model = desktop.getCurrentComponent()

# access the active sheet
active_sheet = model.CurrentController.ActiveSheet

# define useful functions

def getSelectionAddresses(horizontalOffset = 0 , verticalOffset = 0):
    # get the range of addresses from selection
    oSelection = model.getCurrentSelection()
    oArea = oSelection.getRangeAddress()
    return oArea.StartColumn + horizontalOffset, oArea.StartRow + verticalOffset, oArea.EndColumn + horizontalOffset, oArea.EndRow + verticalOffset
    
def reverse(aTuple):
    return tuple(reversed(aTuple))

# main function
def main():
       
    # get the Cell Range
    # use tuple unpacking of getSelectionAddresses returned tuple as parameter of getCellRangeByPosition
    oRangeSource = active_sheet.getCellRangeByPosition(*getSelectionAddresses())
    
    # get data from the Range of cells and store in a tuple
    oDataSource = oRangeSource.getDataArray()
    
    # print to console
    print(oDataSource)
    
    # create a new range of cells
    # from current selection using function getSelectionAddresses with offset
    # you can use the kwarg (keyword argument) horizontalOffset in parameter
    oRangeTarget = active_sheet.getCellRangeByPosition(*getSelectionAddresses(horizontalOffset = 3))
    
    # Reverse the data 
    oReversedSource = reverse(oDataSource)
    # Then set data for the target range using the 'reversed' data from the source range.
    oRangeTarget.setDataArray(oReversedSource)
</code></pre>



<h4 class="wp-block-heading">Walk through the code</h4>



<p>The global variables at the start are what allow us to manipulate LibreOffice Objects like the spreadsheet and its cells.<br>Then the function <strong>getSelectionAddresses()</strong>, as we have seen earlier is to get the addresses of the selected cells on LibreOffice.<br>The function <strong>reverse()</strong> is returning a reversed version of a tuple.</p>



<p> Let&#8217;s focus on the <strong>main</strong>() function.<br>In the main function, The function<strong> getCellRangeByPosition()</strong> to get the cells coordinates of the range of cells, takes 4 arguments, and not a tuple with 4 elements. But our function <strong>getSelectionAddresses</strong>() returns a tuple of 4 elements.  So that is why the argument <strong>getSelectionAddresses</strong>() is preceded with a &#8216;*&#8217; (asterisk). This mean that we are &#8216;<span style="text-decoration: underline;">unpacking</span>&#8216; the tuple returned by the function <strong>getSelectionAddresses</strong>() into a sequence of for single elements.<br>When you create a tuple, you are &#8216;packing&#8217; it with elements. You can &#8216;unpack&#8217; it to access all its elements at once. And the asterisk can do it for you!</p>



<pre class="wp-block-code"><code>    # get the Cell Range
    # use tuple unpacking of getSelectionAddresses returned tuple as parameter of getCellRangeByPosition
    oRangeSource = active_sheet.getCellRangeByPosition(*getSelectionAddresses())
</code></pre>



<p id="block-0425428d-2de8-4591-a39f-ebf88292e19e">Then we are using <strong>getDataArray()</strong> to get the data within the selected range, we are printing the tuple to the console.</p>



<pre id="block-3dd6bda9-e0ff-4d88-a8e5-58c6dcad86be" class="wp-block-code"><code>    # get data from the Range of cells and store in a tuple
    oDataSource = oRangeSource.getDataArray()
    
    # print to console
    print(oDataSource)</code></pre>



<p>Next, we create a new range of cells, using again the &#8216;unpacked&#8217; version of <strong>getSelectionAddresses()</strong> preceded with an asterix, but this time with the argument  &#8216;<strong>horizontalOffset = 3</strong>&#8216;, we don&#8217;t need to specify the <strong>verticalOffset</strong> if we want to use its default vaue set to 0 in the function definition. But we have to use the kwarg (the keyword argument) <strong>horizontalOffset</strong> to make sure we are passing the wanted value to the correct argument.<br>So in this case I have an offset of 3 cells horizontally, the reversed range of data will be displayed 3 cells on the right of the selected data.<br>If you wanted to reverse the range &#8216;in place&#8217; and overwrite the source data, you just need to put no arguments in the code for function <strong>getSelectionAddresses()</strong>.</p>



<pre id="block-3dd6bda9-e0ff-4d88-a8e5-58c6dcad86be" class="wp-block-code"><code>    # create a new range of cells
    # from current selection using function getSelectionAddresses with offset
    # you can use the kwarg (keyword argument) horizontalOffset in parameter
    oRangeTarget = active_sheet.getCellRangeByPosition(*getSelectionAddresses(horizontalOffset = 3))</code></pre>



<pre class="wp-block-verse">Note: there is no exception handling, no safeguard, to check if the offset your enter makes the range being 'out of range'. That could be a further improvement of this program. Another improvement could be to have the offset defined in a cell, or defined using a small control form with a text input.</pre>



<p>Finally, we reverse the tuple of data and store it in our new range of Cell addresses in the LibreOffice Calc sheet.</p>



<pre class="wp-block-code"><code>    # Reverse the data 
    oReversedSource = reverse(oDataSource)
    # Then set data for the target range using the 'reversed' data from the source range.
    oRangeTarget.setDataArray(oReversedSource)</code></pre>



<p>You can also find the file with the full code on <a href="https://github.com/Gweno/tutolibro.tech/tree/master/lopy/part9" target="_blank" rel="noreferrer noopener">this gitHub rep</a>.</p>



<h4 class="wp-block-heading">Test the code</h4>



<p>Now it&#8217;s time to create a range of data, select that rage and run the python macro!</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="500" height="89" src="https://tutolibro.org/wp-content/uploads/2021/05/tutolibro_part9.gif" alt="" class="wp-image-1104"/><figcaption>The selected range is reversed!</figcaption></figure>



<p>You can a look at <a href="https://tutolibro.org/2020/03/11/libreoffice-calc-python-programming-annex-1-assign-a-python-macro-to-a-key/">tutorial Annex 1</a> to map a combination of key to this macro (I use CTRL + 0).<br>I hope this tutorial helped you understand a bit more about using python to control LibreOffice Calc. Please leave a comment to let me know!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tutolibro.org/2021/05/07/python-libreoffice-reverse-the-order-of-cells-content-from-a-cell-range/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1070</post-id>	</item>
		<item>
		<title>LibreOffice Calc &#038; Python Programming: part 8 – From Python Tuple to Cells Range</title>
		<link>https://tutolibro.org/2020/07/17/libreoffice-calc-python-programming-part-8-from-python-tuple-to-cells-range/</link>
					<comments>https://tutolibro.org/2020/07/17/libreoffice-calc-python-programming-part-8-from-python-tuple-to-cells-range/#comments</comments>
		
		<dc:creator><![CDATA[gweno]]></dc:creator>
		<pubDate>Fri, 17 Jul 2020 20:28:03 +0000</pubDate>
				<category><![CDATA[Calc]]></category>
		<category><![CDATA[LibreOffice]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[calc]]></category>
		<category><![CDATA[cell type]]></category>
		<category><![CDATA[libreoffice]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[setDataArray]]></category>
		<guid isPermaLink="false">https://tutolibro.tech/?p=1017</guid>

					<description><![CDATA[This time we are going to create a new Range of Cells and fill it with the data stored in our tuple created in part 7. Here is the plan for this tutorial: Start with code from the previous chapter...<br /><a class="read-more-button" href="https://tutolibro.org/2020/07/17/libreoffice-calc-python-programming-part-8-from-python-tuple-to-cells-range/">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>This time we are going to create a new Range of Cells and fill it with the data stored in our tuple created in <a href="https://tutolibro.org/2020/07/10/libreoffice-calc-python-programming-part-7-from-cells-range-to-python-tuple/">part 7</a>.</p>



<h4 class="wp-block-heading">Here is the plan for this tutorial:</h4>



<ul class="wp-block-list">
<li>Start with code from the previous chapter</li>



<li>Set the top-left and bottom-right Cells addresses</li>



<li>Set the Target Range</li>



<li>Create a new Array of data</li>
</ul>



<h4 class="wp-block-heading">Start with code from the previous chapter</h4>



<p>Starting with the code from the previous episode of this series LibreOffice Calc &amp; Python Programming from its corresponding <a rel="noreferrer noopener" href="https://github.com/Gweno/tutolibro.tech/tree/master/lopy/part7" target="_blank">gitHub rep</a>, or a copy paste here:</p>



<pre class="wp-block-code"><code>def context():
    
    # set global variables for context
    
    global desktop
    global model
    global active_sheet
    
    # get the doc from the scripting context 
    # which is made available to all scripts
    desktop = XSCRIPTCONTEXT.getDesktop()
    model = desktop.getCurrentComponent()
    
    # access the active sheet
    active_sheet = model.CurrentController.ActiveSheet
    
def main():
    
    # call function context()
    context()
    
    # get the range of addresses from selection
    oSelection = model.getCurrentSelection()
    oArea = oSelection.getRangeAddress()

    # store the attribute of CellRangeAddress 
    nLeft = oArea.StartColumn
    nTop = oArea.StartRow
    nRight = oArea.EndColumn
    nBottom = oArea.EndRow
    #(note: could the attribute directly instead of using intermediary variable)
    
    # get the Cell Range 
    oRangeSource = active_sheet.getCellRangeByPosition(nLeft, nTop, nRight, nBottom)
    
    # example by name:
    # ~ oRangeSource = active_sheet.getCellRangeByName('A1:C10')
    
    # get data from the Range of cells and store in a tuple
    oDataSource = oRangeSource.getDataArray()
    
    # print to console
    print(oDataSource)
</code></pre>



<h4 class="wp-block-heading">Set  the top-left and bottom-right Cells addresses</h4>



<p>This step is to calculate the addresses for our target range of cells, by defining the columns and rows for the top-left and bottom-right cells or our target range, the range where we are going to transfer the data from the selected area.<br>To avoid having python to throw an error, we need to make sure that our target area is exactly the same size than our source area.<br>We also don&#8217;t want to overlap our source area with our target area.<br>In this example, let&#8217;s define an area starting two columns to the right of our selected area. So the addresses of the cells in the new range will depend on the addresses of cells within the source range.<br>We can set an offset value that will define how many columns to the right of our selected range will our target range will be.</p>



<p>For example:<br><strong>offset = 2</strong></p>



<p>Then we set the leftmost column of our new range to be like this:<br><strong>tLeft = nRight + offset</strong><br>With <strong>nRight</strong> being the right column of our range of selected cells.<br>So here we are simply adding the offset (=2) to the end column of the source range.</p>



<p>Then we need to know the number of columns in the source area:<br><strong>nbCol = nRight &#8211; nLeft + 1</strong><br>This is the difference between the address of the right column of the source area and the address of the left column area, to which we add 1.<br>Check the illustration below to understand:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="769" height="73" src="https://tutolibro.org/wp-content/uploads/2020/07/lopy-part8_0.png" alt="" class="wp-image-1055" srcset="https://tutolibro.org/wp-content/uploads/2020/07/lopy-part8_0.png 769w, https://tutolibro.org/wp-content/uploads/2020/07/lopy-part8_0-300x28.png 300w" sizes="auto, (max-width: 769px) 100vw, 769px" /><figcaption class="wp-element-caption">There are 3 three columns in the yellow range starting at number 2, ending at number 4:<br>(4-2)+1 = 2 + 1 = 3</figcaption></figure>



<p>To remember that logic I always use a metaphor about number of holidays: if I start my holidays the 2nd of the month and my last day of holidays is the 4th of the month, I know I had 3 days of holidays, the 2nd, the 3rd and the 4th. And first day subtracted to last day makes <strong>4 -2 = 2</strong> , and I need to <strong>add 1</strong> day to have the right count: 3 days from the 2nd to the 4th.<br>In the illustration above, the column 2 is the day 2 of the month, the column 4, the day 4&#8230;</p>



<p>To set the address of the last column of our target range we do the following:<br><strong>tRight = nRight + nbCol &#8211; 1 + offset</strong><br>Starting from the last column of the source area, you add the number of columns in that source area, subtract 1, and then add the same offset that you used for the starting column of this new range.<br>To use the same number of holidays example, to know what are the starting date and ending date of my holidays knowing that I have 3 days off next week, I need to add the number of days off to the starting date and take away 1: 2+3=5, 5-1 = 4 -&gt; the 4th.</p>



<p>We can keep the same rows than the source area for the target area:<br><strong>tTop = nTop<br>tBottom = nBottom</strong></p>



<p>Altogether the snippet for setting the columns and rows of our new range is:</p>



<pre class="wp-block-code"><code>    # set the target columns and rows
    # relative to the selected area
    offset = 2
    tLeft = nRight + offset
    nbCol = nRight - nLeft + 1
    tRight = nRight + nbCol - 1 + offset
    tTop = nTop
    tBottom = nBottom

    print(tLeft,tTop,tRight,tBottom)</code></pre>



<p>A simplified version, of <strong>tRight</strong>, if you replace nbCol by its value, would be:<br><strong>tRight = 2*nRight &#8211; nLeft + offset</strong><br>In which case you don&#8217;t need the nbCol variable anymore, but to make the explanation easier I am keeping it.</p>



<p>As usual, to help with testing, I added a print statement. It will print the value you calculated in the console. You can read my tutorial <a href="https://tutolibro.org/2020/02/24/libreoffice-calc-python-programming-part-4-using-apso-console-to-print-text/">about the APSO console</a> if you haven&#8217;t yet. Also to make testing easier, I usually assign the program to a combination of key, like CTRL + 0. Check <a href="https://tutolibro.org/2020/03/11/libreoffice-calc-python-programming-annex-1-assign-a-python-macro-to-a-key/">my post</a> that explains how to do that easily.</p>



<h4 class="wp-block-heading">Set the Target range</h4>



<p>We are going to use <strong>getCellRangeByPosition</strong> again to create a range of cells, but this time we are not going to use the addresses of the area defined by the mouse selection. We are now going to use the variables that we created in the previous step <strong>tLeft, tTop, tRight, tBottom</strong>.</p>



<pre class="wp-block-code"><code>    # create target Range
    oRangeTarget = active_sheet.getCellRangeByPosition(tLeft, tTop, tRight, tBottom)</code></pre>



<p>Now that we have define a cell range, we can assign data to it.</p>



<h4 class="wp-block-heading">Create a new Array of data</h4>



<p>In the <a href="https://tutolibro.org/2020/07/10/libreoffice-calc-python-programming-part-7-from-cells-range-to-python-tuple/">last tutorial</a> we used the function getDataArray() to create a python tuple that we named oDataSource from the data stored in the source range of cells. This time we are going to use the function setDataArray() with the existing tuple of data oDataSource as parameter.</p>



<p>This will store the data from the tuple oDataSource to the target Range of Cells that we defined earlier, and hopefully display the data in the cells on the LibreOffice current spreadsheet.</p>



<pre class="wp-block-code"><code>    # set data for the target range using datafrom the source range.
    oRangeTarget.setDataArray(oDataSource)</code></pre>



<p>Here is what I get with a bit of data, including the APSO console:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="500" height="353" src="https://tutolibro.org/wp-content/uploads/2020/07/lopy-part8_1.gif" alt="" class="wp-image-1061"/><figcaption class="wp-element-caption">Simple example</figcaption></figure>



<p>This is the full code:</p>



<pre class="wp-block-code"><code>def context():
    
    # set global variables for context
    
    global desktop
    global model
    global active_sheet
    
    # get the doc from the scripting context 
    # which is made available to all scripts
    desktop = XSCRIPTCONTEXT.getDesktop()
    model = desktop.getCurrentComponent()
    
    # access the active sheet
    active_sheet = model.CurrentController.ActiveSheet
    
def main():
    
    # call function context()
    context()
    
    # get the range of addresses from selection
    oSelection = model.getCurrentSelection()
    oArea = oSelection.getRangeAddress()

    # store the attribute of CellRangeAddress 
    nLeft = oArea.StartColumn
    nTop = oArea.StartRow
    nRight = oArea.EndColumn
    nBottom = oArea.EndRow
    #(note: could the attribute directly instead of using intermediary variable)
    
    # get the Cell Range 
    oRangeSource = active_sheet.getCellRangeByPosition(nLeft, nTop, nRight, nBottom)
    
    # example by name:
    # ~ oRangeSource = active_sheet.getCellRangeByName('A1:C10')
    
    # get data from the Range of cells and store in a tuple
    oDataSource = oRangeSource.getDataArray()
    
    # print to console
    print(oDataSource)
    
    # set the target columns and rows
    # relative to the selected area
    offset = 2
    tLeft = nRight + offset
    nbCol = nRight - nLeft + 1
    tRight = nRight + nbCol - 1 + offset
    tTop = nTop
    tBottom = nBottom
    
    print(tLeft,tTop,tRight,tBottom)
    
    # create target Range
    oRangeTarget = active_sheet.getCellRangeByPosition(tLeft, tTop, tRight, tBottom)
    
    # set data for the target range using data from the source range.
    oRangeTarget.setDataArray(oDataSource)</code></pre>



<p>You can also find this code on <a href="https://github.com/Gweno/tutolibro.tech/tree/master/lopy/part8" target="_blank" rel="noreferrer noopener">this gitHub rep</a>.</p>



<p>The getDataArray() function creates a tuple of tuples. Tuples are immutable objects, so you cannot change them once you have created them.<br>So if you want to change the data that you stored from a range of cells, you will need to create a new tuple, while looping on the source tuple element by element.<br>In the next episode of this series of Tutorials about LibreOffice Calc and Python Programming, I will show you some examples on how to work with these tuples of tuples to work on the data.</p>



<p>If you like this tutorial, you could <a href="https://buymeacoffee.com/tutolibro" data-type="link" data-id="https://buymeacoffee/tutolibro" target="_blank" rel="noreferrer noopener">buy me a coffee</a> to help me continue writing add-free tutorials.</p>



<p>Thank you!</p>



<div class="wp-block-group is-content-justification-space-between is-nowrap is-layout-flex wp-container-core-group-is-layout-0dfbf163 wp-block-group-is-layout-flex">

</div>
]]></content:encoded>
					
					<wfw:commentRss>https://tutolibro.org/2020/07/17/libreoffice-calc-python-programming-part-8-from-python-tuple-to-cells-range/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1017</post-id>	</item>
		<item>
		<title>LibreOffice Calc &#038; Python Programming: part 7 – From Cells Range to Python Tuple.</title>
		<link>https://tutolibro.org/2020/07/10/libreoffice-calc-python-programming-part-7-from-cells-range-to-python-tuple/</link>
					<comments>https://tutolibro.org/2020/07/10/libreoffice-calc-python-programming-part-7-from-cells-range-to-python-tuple/#comments</comments>
		
		<dc:creator><![CDATA[gweno]]></dc:creator>
		<pubDate>Fri, 10 Jul 2020 23:54:50 +0000</pubDate>
				<category><![CDATA[Calc]]></category>
		<category><![CDATA[LibreOffice]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[calc]]></category>
		<category><![CDATA[cell type]]></category>
		<category><![CDATA[getDataArray]]></category>
		<category><![CDATA[libreoffice]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">https://tutolibro.tech/?p=998</guid>

					<description><![CDATA[The topic for this episode of my LibreOffice Calc &#38; Python Programming tutorial series is to get the data stored in a range of cells in LibreOffice. And we are going to do that using some very useful dedicated Pythons...<br /><a class="read-more-button" href="https://tutolibro.org/2020/07/10/libreoffice-calc-python-programming-part-7-from-cells-range-to-python-tuple/">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>The topic for this episode of my LibreOffice Calc &amp; Python Programming tutorial series is to get the data stored in a range of cells in LibreOffice. And we are going to do that using some very useful dedicated Pythons Functions delivered with the PyUno library.</p>



<h4 class="wp-block-heading">How are we going to do it?</h4>



<p>We are going to get the coordinates of a range of selected cells in an open Calc document and store all the data that the range of cells contains into an Tuple.</p>



<p>But first, what is an <strong>Tuple</strong>?</p>



<p>A Tuple in Python is like an Array of data but that can store data with different types.<br>But what is an Array?<br>An array in computer programming is a container that stores data in consecutive memory addresses. It is widely used in many programming languages.<br>In Python an Array is used to store many variables with the same type of data (string, integer, float, etc&#8230;) which is not convenient for storing data coming from a Spreadsheet&#8217;s cells.<br>That is where the Tuple is convenient as it can store data of different types (see the 4 possible types in<a href="https://tutolibro.org/2020/06/26/libreoffice-calc-python-programming-part-6-type-of-a-cell-content/"> my previous episode</a> of this series).<br>Note that a Tuple in Python is &#8216;immutable&#8217;, it means that we cannot change its content once it has been defined. It is important to know and I&#8217;ll show you how to work with tuples easily.<br>So let&#8217;s get Started.</p>



<h4 class="wp-block-heading">Here is the plan for this tutorial:</h4>



<ul class="wp-block-list">
<li>Set the context for global variables</li>



<li>Get the Range of Addresses</li>



<li>Get the data from a range of Cells by Position</li>



<li>Get the data from a range of Cells by Name</li>



<li>Store Cells content in an Tuple of Data</li>
</ul>



<h4 class="wp-block-heading">Set the context for global variables</h4>



<pre class="wp-block-verse">Note: you can start from the same script as the <a href="https://tutolibro.org/2020/06/26/libreoffice-calc-python-programming-part-6-type-of-a-cell-content/">previous tutorial</a> (part 6 - Cells Types ).</pre>



<p>Starting with our usual context() function that stores desktop , model and active_sheet at a global scope:</p>



<pre class="wp-block-code"><code>def context():
    
    # set global variables for context
    
    global desktop
    global model
    global active_sheet
    
    # get the doc from the scripting context 
    # which is made available to all scripts
    desktop = XSCRIPTCONTEXT.getDesktop()
    model = desktop.getCurrentComponent()
    
    # access the active sheet
    active_sheet = model.CurrentController.ActiveSheet</code></pre>



<h4 class="wp-block-heading">Get the Range of Addresses</h4>



<p>In our <strong>main</strong> function we start by calling <strong>context</strong>(), then we need to get the Addresses of the cells .</p>



<pre class="wp-block-code"><code>def main():
    
    # call function context()
    context()
    
    # get the range of addresses from selection
    oSelection = model.getCurrentSelection()
    oArea = oSelection.getRangeAddress()</code></pre>



<p>The method <strong>getRangeAddress</strong>() returns a <strong>CellRangeAddress</strong>.<br> A <strong>CellRangeAddress</strong> is a Struct (short for Structure). It has the following Attributes:</p>



<p><strong>Sheet, StartColumn, StartRow, EndRow, EndColumn.</strong></p>



<p>We don&#8217;t really need the <strong>Sheet</strong> index yet as we are only working on the current sheet. But we need the 4 other attributes. They correspond to the top-left and bottom-right cells of what we have selected with the mouse.</p>



<p>I strongly advise you to check <a rel="noreferrer noopener" href="https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1sheet_1_1XCellRangeData.html#details" target="_blank"><strong>XCellRangeAddress</strong></a> and explore the LibreOffice API. It is actually a really good way to discover the different methods and attributes that you can use.</p>



<p>The next step is to get all necessary cell references to retrieve data from a Range of Cells. We can do that now that we have our <strong>oArea</strong> object variable. </p>



<pre class="wp-block-code"><code>    # store the attribute of CellRandeAddress 
    nLeft = oArea.StartColumn
    nTop = oArea.StartRow
    nRight = oArea.EndColumn
    nBottom = oArea.EndRow
    #(note: could the attribute directly instead of using intermediary variable)</code></pre>



<pre class="wp-block-verse">Note that although we could use the <strong>oArea</strong> attributes, storing them in variables with relevant names makes the program/script more readable.</pre>



<h4 class="wp-block-heading">Get the data from a range of Cells by Position</h4>



<p>Now we can call function <strong>getCellRangeByPosition</strong> to returns a &#8216;sub-range&#8217; of the active sheet. Understand that the active sheet itself is a range of cells that is much bigger.<br>That &#8216;sub-range&#8217; is the range of Selected Cells from where we are going to extract data. I am calling that range <strong>oRangeSource</strong>.</p>



<pre class="wp-block-code"><code>    # get data from the source
    oRangeSource = active_sheet.getCellRangeByPosition(nLeft, nTop, nRight, nBottom)</code></pre>



<p>Here is an example of a selected range of cells in LibreOffice:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="305" height="169" src="https://tutolibro.org/wp-content/uploads/2020/07/lopy-part7-1.png" alt="" class="wp-image-1014" srcset="https://tutolibro.org/wp-content/uploads/2020/07/lopy-part7-1.png 305w, https://tutolibro.org/wp-content/uploads/2020/07/lopy-part7-1-300x166.png 300w" sizes="auto, (max-width: 305px) 100vw, 305px" /><figcaption class="wp-element-caption">From Top-Left to Bottom-Right</figcaption></figure>



<h4 class="wp-block-heading">Get the data from a range of Cells by Name</h4>



<p>In this tutorial we are using variables to get the Range of Cells. We could also use arbitrary values corresponding to the Top-left and Bottom-Right cells of the range like:</p>



<pre class="wp-block-code"><code>oRangeSource = active_sheet.getCellRangeByPosition(0, 0, 2, 9)</code></pre>



<p>That set of parameters (0, 0, 2, 9) means that we are getting the range from cell(0,0) to cell(2,9).<br>In some cases it is easier to refer the cells by name. With names instead of positions the range (0,0,2,9) would be from cell &#8220;A1&#8221; to cell &#8220;C10&#8221;.</p>



<p>If you work with a range of cells by name it is then much easier to use the dedicated function <strong>getCellRangeByName</strong>:</p>



<pre class="wp-block-code"><code>    # example by name:
    oRangeSource = active_sheet.getCellRangeByName('A1:C10')</code></pre>



<p>You would define the range of cells the same way you do it in formulas: <strong>&#8216;A1:C10</strong>&#8216;.</p>



<p>Using range by position is much easier in programs where the ranges are not always the same and can be dynamically changed. It makes it much more flexible to work with, especially if you need to run loops on the cells.</p>



<h4 class="wp-block-heading">Store Cells content in an Tuple of Data</h4>



<p>This is a key operation.<br>The function <strong>getDataArray</strong> extracts the content of the cells within a range and stores that content in a tuple. And from there we will be able to use that content easily with Python. Here is the simple line of code needed to do that:</p>



<pre class="wp-block-code"><code>    # get data from the Range of cells and store in a tuple
    oDataSource = oRangeSource.getDataArray()</code></pre>



<pre class="wp-block-verse">Note: A <strong>print</strong> statement here would be helpful to check how the tuple of data looks like. To get the APSO console <a href="https://tutolibro.org/2020/02/24/libreoffice-calc-python-programming-part-4-using-apso-console-to-print-text/">check part 4 </a> of this series of tutorials).</pre>



<pre class="wp-block-code"><code>    # print to console
    print(oRangeSource)</code></pre>



<p>Here is an example of what you would get:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="715" height="306" src="https://tutolibro.org/wp-content/uploads/2020/07/lopy-part7-0.png" alt="" class="wp-image-1009" srcset="https://tutolibro.org/wp-content/uploads/2020/07/lopy-part7-0.png 715w, https://tutolibro.org/wp-content/uploads/2020/07/lopy-part7-0-300x128.png 300w" sizes="auto, (max-width: 715px) 100vw, 715px" /><figcaption class="wp-element-caption">From a LibreOffice Range of Cells to a Python&#8217;s Tuple!</figcaption></figure>



<p>The Tuple produced is actually a tuple of tuples:</p>



<p>((1.0, &#8216;C&#8217;), (2.0, &#8216;D&#8217;), (&#8216;A&#8217;, 3.0), (&#8216;B&#8217;, 4.0))</p>



<p>As you can see each tuple inside the big tuple stores a row of data.<br>If you look closer, for example if you look at the tuple for the first row:</p>



<p>(1.0,&#8217;C&#8217;)</p>



<p>You will see that the 1.0 has no quote where the &#8216;C&#8217; has quotes. This means that the types of the data within the cells have been preserved.<br>A number in LibreOffice remains a number in Python, and string remains a string. In fact the function <strong>getDataArray</strong>() returns a tuple of tuples with data of a type <strong>Double</strong> or <strong>String</strong>. Double is a type for any decimal numbers.</p>



<p>Now here is the full code for this tutorial:</p>



<pre class="wp-block-code"><code>def context():
    
    # set global variables for context
    
    global desktop
    global model
    global active_sheet
    
    # get the doc from the scripting context 
    # which is made available to all scripts
    desktop = XSCRIPTCONTEXT.getDesktop()
    model = desktop.getCurrentComponent()
    
    # access the active sheet
    active_sheet = model.CurrentController.ActiveSheet
    
def main():
    
    # call function context()
    context()
    
    # get the range of addresses from selection
    oSelection = model.getCurrentSelection()
    oArea = oSelection.getRangeAddress()

    # store the attribute of CellRangeAddress 
    nLeft = oArea.StartColumn
    nTop = oArea.StartRow
    nRight = oArea.EndColumn
    nBottom = oArea.EndRow
    #(note: could the attribute directly instead of using intermediary variable)
    
    # get the Cell Range 
    oRangeSource = active_sheet.getCellRangeByPosition(nLeft, nTop, nRight, nBottom)
    
    # example by name:
    # ~ oRangeSource = active_sheet.getCellRangeByName('A1:C10')
    
    # get data from the Range of cells and store in a tuple
    oDataSource = oRangeSource.getDataArray()
    
    # print to console
    print(oDataSource)</code></pre>



<p>On gitHub: <a href="https://github.com/Gweno/tutolibro.tech/tree/master/lopy/part7" target="_blank" rel="noreferrer noopener">https://github.com/Gweno/tutolibro.tech/tree/master/lopy/part7</a></p>



<p>To make it easier to test my scripts I usually assign them to a combination of keys like CTRL + 0. Learn how to do it on <a href="https://tutolibro.org/2020/03/11/libreoffice-calc-python-programming-annex-1-assign-a-python-macro-to-a-key/">this post</a>.</p>



<p>In the next tutorials we will actually do something with the tuple created here and then play a little bit the data inside.</p>



<pre class="wp-block-verse">Please leave a comment to let me know what you think about this tutorial 
or if you had any issues going through it. Getting your comments helps 
me a lot to make the next tutorials better! Thank you!</pre>



<p>If you like this tutorial, you could <a href="https://buymeacoffee.com/tutolibro" data-type="link" data-id="https://buymeacoffee/tutolibro" target="_blank" rel="noreferrer noopener">buy me a coffee</a> to help me continue writing add-free tutorials.</p>



<p>Thank you!</p>



<div class="wp-block-group is-content-justification-space-between is-nowrap is-layout-flex wp-container-core-group-is-layout-0dfbf163 wp-block-group-is-layout-flex">

</div>
]]></content:encoded>
					
					<wfw:commentRss>https://tutolibro.org/2020/07/10/libreoffice-calc-python-programming-part-7-from-cells-range-to-python-tuple/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">998</post-id>	</item>
		<item>
		<title>LibreOffice Calc &#038; Python Programming: part 6 – Type of a Cell content.</title>
		<link>https://tutolibro.org/2020/06/26/libreoffice-calc-python-programming-part-6-type-of-a-cell-content/</link>
					<comments>https://tutolibro.org/2020/06/26/libreoffice-calc-python-programming-part-6-type-of-a-cell-content/#comments</comments>
		
		<dc:creator><![CDATA[gweno]]></dc:creator>
		<pubDate>Fri, 26 Jun 2020 23:19:21 +0000</pubDate>
				<category><![CDATA[Calc]]></category>
		<category><![CDATA[LibreOffice]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[calc]]></category>
		<category><![CDATA[cell type]]></category>
		<category><![CDATA[libreoffice]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">https://tutolibro.tech/?p=734</guid>

					<description><![CDATA[In this episode of my LibreOffice Calc &#38; Python Programming tutorial series I am going to talk about the different types of data stored in a LibreOffice cell, and what type to use in the Python code to keep the...<br /><a class="read-more-button" href="https://tutolibro.org/2020/06/26/libreoffice-calc-python-programming-part-6-type-of-a-cell-content/">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>In this episode of my LibreOffice Calc &amp; Python Programming tutorial series I am going to talk about the different types of data stored in a LibreOffice cell, and what type to use in the Python code to keep the same data type than in LibreOffice.</p>



<p>A cell within a LibreOffice Table has no predefined type. Its type comes from its content and can only be one of the 4 following types:</p>



<ul class="wp-block-list">
<li>empty</li>



<li>value</li>



<li>string</li>



<li>formula</li>
</ul>



<p>These types names are quite self-explanatory:</p>



<ul class="wp-block-list">
<li><strong>empty</strong> is simply the type of an empty LibreOffice Calc cell.</li>



<li><strong>value</strong> is the type of any numerical content of a LibreOffice Calc cell.</li>



<li><strong>string</strong> is the type of any text content of a LibreOffice Calc cell.</li>



<li><strong>formula</strong> is the type of any LibreOffice Calc cell that contain a formula.</li>
</ul>



<p>Note:<br>Dates, currencies, decimals, booleans within LibreOffice are not <strong>types</strong> but different <strong>formats</strong> of numbers. We&#8217;ll see how to manage them in a later post.</p>



<p>A good way to illustrate the 4 different cell types is to play with them with a simple python code that will display in the console the type of cell selected in LibreOffice Calc.<br>Please refer to my previous tutorials for <a href="https://tutolibro.org/2019/08/16/libreoffice-calc-python-programming-part-2-hello-world/" target="_blank" rel="noreferrer noopener">creating a program</a> and using the <a rel="noreferrer noopener" href="https://tutolibro.org/2020/02/24/libreoffice-calc-python-programming-part-4-using-apso-console-to-print-text/" target="_blank">APSO console</a>.</p>



<p>First you need to define the variables provided by XSCRIPTCONTEXT. This XSCRIPTCONTEXT is a UNO object that gather all you need to manipulate LibreOffice Documents with Python scripts.</p>



<p>You can either define these variables at the global level of your program or like I like to do, in a separate function that I call context() to make it more customizable in later programs.</p>



<pre class="wp-block-code"><code>def context():
    
    # set global variables for context
    
    global desktop
    global model
    global active_sheet
    
    # get the doc from the scripting context 
    # which is made available to all scripts
    desktop = XSCRIPTCONTEXT.getDesktop()
    model = desktop.getCurrentComponent()
    
    # access the active sheet
    active_sheet = model.CurrentController.ActiveSheet</code></pre>



<p>In this &#8216;context()&#8217; method, we first declare the 3 useful variables that will hold our objects as Global Variables. This will allow us to access these objects from other functions, like out main() function. These objects were briefly explained in <a href="https://tutolibro.org/2019/08/16/libreoffice-calc-python-programming-part-2-hello-world/" target="_blank" rel="noreferrer noopener">part 2</a> of these series of tutorials.</p>



<p><strong>Next</strong> we can create our <strong>main</strong> function:</p>



<ul class="wp-block-list">
<li>call (execute) function <strong>context</strong></li>



<li>get the selected range</li>



<li>get coordinates of the selected cell</li>



<li>get the Type of the selected cell</li>



<li>print in the console and in a cell (optional)</li>
</ul>



<p>But first, to make testing easier I advise to bind our <strong>main()</strong> function to a combination of keys on your keyboard. Check out my <a href="https://tutolibro.org/2020/03/11/libreoffice-calc-python-programming-annex-1-assign-a-python-macro-to-a-key/" target="_blank" rel="noreferrer noopener">Annex1</a> to learn how to do it quickly.</p>



<h4 class="wp-block-heading">Call context</h4>



<p>This is the easiest part, simply:</p>



<pre class="wp-block-code"><code>    # call function context()
    context()</code></pre>



<h4 class="wp-block-heading">Get the selected range</h4>



<p>To do that we use the method <strong>getCurrentSelection()</strong> of the object &#8216;model&#8217; that we defined in the context() method further up.<br>That object &#8216;model&#8217; is an interface for the &#8216;Desktop&#8217; environment that we defined in context().<br>For now we should focus on the end point, the cells themselves. I will write a tutorial to explain how about the Desktop, Interface, Frames and other types of components imported from the UNO library that pyUno is based on.<br>Once we have an object that contains the selection, we can use the method getRangeAddress() to get useful attribues of this object that we will need to access the value of the cell we want and then the type of that value:</p>



<pre class="wp-block-code"><code>    # get the range of addresses from selection
    oSelection = model.getCurrentSelection()
    oArea = oSelection.getRangeAddress()</code></pre>



<h4 class="wp-block-heading">Get the coordinates of the selected cell</h4>



<p>The object &#8216;oArea&#8217; is a range of Cell Addresses and has 5 attributes:</p>



<ul class="wp-block-list">
<li>Sheet: the sheet number in the collection of sheets in the Calc document, starting at 0 for the first sheet.</li>



<li>StartColumn: the index of the first column of the range of cells, starting at 0.</li>



<li>StartRow: the index of the first Row of the range of cells, starting at 0.</li>



<li>EndColumn: the index of the last column of the range of cells.</li>



<li>EndRow: the index of the last row of the range of cells.</li>
</ul>



<p>In our case we are only interested in the first cell of the selection. Whether we have selected one cell or more we are only going to use the attributes <strong>StartColumn</strong> and <strong>StartRow</strong>. Using these 2 values will then let us access the cell using the <strong>getCellByPosition()</strong> method:</p>



<pre class="wp-block-code"><code>    # get the first cell
    firstRow = oArea.StartRow
    firstCol = oArea.StartColumn
    selectedCell = active_sheet.getCellByPosition(firstCol,firstRow)</code></pre>



<h4 class="wp-block-heading">Get the Type of the selected cell</h4>



<p>Now we have in hand the cell we want, we can check its attribute <strong>Type</strong> directly with <strong>selectedCell.Type</strong>.<br>However this would give us a detailed description of that attribute, a bit too detailed like that:<br>&lt;Enum instance com.sun.star.table.CellContentType(&#8216;TEXT&#8217;)&gt;<br>This tells us that the attribute <strong>Type</strong> is in fact a python object of type <span style="text-decoration: underline;">Enum</span>.<br>And to get the value of an object of type Enum we simply need to add .value like this:<br> <strong>selectedCell.Type.value</strong><br>So our code for this part is:</p>



<pre class="wp-block-code"><code>    # get the type of the cell
    cellType = selectedCell.Type.value</code></pre>



<h4 class="wp-block-heading">Print in the console and in a cell (optional)</h4>



<p>To get the console I strongly advice to use the APSO add-on which is so good, so free and just essential to make your life easier wen using Python scripts with LibreOffice, check <a rel="noreferrer noopener" href="https://tutolibro.org/2020/02/24/libreoffice-calc-python-programming-part-4-using-apso-console-to-print-text/" target="_blank">part 4</a> of these LibreOffice/Python tutorials to get APSO and to install it. Then you can use the Python <strong>print()</strong> function to display the type of our cell in the Console.<br>When working on a Python scrip sometime it&#8217;s easier to display directly in a cell, just use the the method <strong>getCellByPosition()</strong> to set the value of a wanted cell, for example the next cell on the same row as our selected cell.<br>Note that we don&#8217;t need to convert cellType to a string because the value of the Enum Type is a string.</p>



<pre class="wp-block-code"><code>    # print in console
    print("Cell (",firstCol,",",firstRow,") Type:", cellType)
    
    # display in next cell
    active_sheet.getCellByPosition(firstCol+1,firstRow).String = "Cell Type:" + cellType</code></pre>



<h4 class="wp-block-heading">Full script for main()</h4>



<pre class="wp-block-code"><code>def main():
    
    # call function context()
    context()
    
    # get the range of addresses from selection
    oSelection = model.getCurrentSelection()
    oArea = oSelection.getRangeAddress()
        
    # get the first cell
    firstRow = oArea.StartRow
    firstCol = oArea.StartColumn
    selectedCell = active_sheet.getCellByPosition(firstCol,firstRow)
    
    # get the type of the cell
    cellType = selectedCell.Type.value
    
    # print in console
    print("Cell (",firstCol,",",firstRow,") Type:", cellType)
    
    # display in next cell
    active_sheet.getCellByPosition(firstCol+1,firstRow).String = "Cell Type:" + cellType</code></pre>



<h3 class="wp-block-heading">Full script with both functions:</h3>



<pre class="wp-block-code"><code># Created by Gwenole Capp 18/06/2020
# For tutolibro.tech
# Public Domain, feel free to copy, modify, use in your own scripts
# 
# email: gwenole.capp@gmail.com

def context():
    
    # set global variables for context
    
    global desktop
    global model
    global active_sheet
    
    # get the doc from the scripting context 
    # which is made available to all scripts
    desktop = XSCRIPTCONTEXT.getDesktop()
    model = desktop.getCurrentComponent()
    
    # access the active sheet
    active_sheet = model.CurrentController.ActiveSheet
    
def main():
    
    # call function context()
    context()
    
    # get the range of addresses from selection
    oSelection = model.getCurrentSelection()
    oArea = oSelection.getRangeAddress()
        
    # get the first cell
    firstRow = oArea.StartRow
    firstCol = oArea.StartColumn
    selectedCell = active_sheet.getCellByPosition(firstCol,firstRow)
    
    # get the type of the cell
    cellType = selectedCell.Type.value
    
    # print in console
    print("Cell (",firstCol,",",firstRow,") Type:", cellType)
    
    # display in next cell
    active_sheet.getCellByPosition(firstCol+1,firstRow).String = "Cell Type:" + cellType
</code></pre>



<h3 class="wp-block-heading">On gitHub:</h3>



<p>Download or clone from <a href="https://github.com/Gweno/tutolibro.tech/tree/master/lopy/part6" target="_blank" rel="noreferrer noopener">this folder</a> on my gitHub repository.</p>



<p>If you are not familiar with git and gitHub you check <a rel="noreferrer noopener" href="https://tutolibro.org/2020/02/06/libreoffice-calc-python-programming-annex-0-version-control-with-git/" target="_blank">this post</a> I wrote as Annex to these series of tutorials.</p>



<h4 class="wp-block-heading">Leave a comment</h4>



<p>Please leave a comment to tell me what you think of this tutorial or if you have any question.</p>



<p>If you like this tutorial, you could <a href="https://buymeacoffee.com/tutolibro" data-type="link" data-id="https://buymeacoffee/tutolibro" target="_blank" rel="noreferrer noopener">buy me a coffee</a> to help me continue writing add-free tutorials.</p>



<p>Thank you!</p>



<div class="wp-block-group is-content-justification-space-between is-nowrap is-layout-flex wp-container-core-group-is-layout-0dfbf163 wp-block-group-is-layout-flex">

</div>
]]></content:encoded>
					
					<wfw:commentRss>https://tutolibro.org/2020/06/26/libreoffice-calc-python-programming-part-6-type-of-a-cell-content/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">734</post-id>	</item>
		<item>
		<title>LibreOffice Calc &#038; Python Programming: Annex 1 – Assign a Python Macro to a key.</title>
		<link>https://tutolibro.org/2020/03/11/libreoffice-calc-python-programming-annex-1-assign-a-python-macro-to-a-key/</link>
					<comments>https://tutolibro.org/2020/03/11/libreoffice-calc-python-programming-annex-1-assign-a-python-macro-to-a-key/#comments</comments>
		
		<dc:creator><![CDATA[gweno]]></dc:creator>
		<pubDate>Wed, 11 Mar 2020 23:33:51 +0000</pubDate>
				<category><![CDATA[Calc]]></category>
		<category><![CDATA[LibreOffice]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://tutolibro.tech/?p=755</guid>

					<description><![CDATA[This episode of my LibreOffice Calc &#38; Python Programming tutorial is an annex to the normal series. In this article I am going to show you a quick way to execute your python scripts.The idea is simple: you assign a...<br /><a class="read-more-button" href="https://tutolibro.org/2020/03/11/libreoffice-calc-python-programming-annex-1-assign-a-python-macro-to-a-key/">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>This episode of my LibreOffice Calc &amp; Python Programming tutorial is an annex to the normal series. In this article I am going to show you a quick way to execute your python scripts.<br>The idea is simple: you assign a combination of keyboard keys to any of your Python scripts (I also called them programs, it sounds more pro!).</p>



<p>Here is the plan for this Annex 0 of the tutorial:</p>



<ul class="wp-block-list">
<li><a href="#write">Write a simple python program</a>.</li>



<li><a href="#save">Save the script at the right place</a>.</li>



<li><a href="#assign">Assign your scrip to [CTRL]+0.</a></li>
</ul>



<h4 class="wp-block-heading" id="write">Write a simple python program.</h4>



<p>Let&#8217;s make a quick python program that writes numbers from 1 to 10 in 10 consecutive cells in column B of any LibreOffice Calc Spreadsheet (yes a lot like in <a href="https://tutolibro.org/2019/09/18/libreoffice-calc-python-programming-part-3-the-for-loop/">this tutorial!</a>).</p>



<pre class="wp-block-code"><code>
# get the doc from the scripting context 
# which is made available to all scripts
desktop = XSCRIPTCONTEXT.getDesktop()
model = desktop.getCurrentComponent()

# access the active sheet
active_sheet = model.CurrentController.ActiveSheet

def write_1_to_10(*args):
    """Write 1,2...10 in Column B"""
    for each_number in range(10):
        active_sheet.getCellByPosition(1,each_number).Value = each_number + 1</code></pre>



<p>In this simple example we don&#8217;t use a main() program to call our function &#8216;write_1_to_10, so the function needs to have the *args (pointer to arguments) for passing information from the LibreOffice environment to Python.</p>



<h4 class="wp-block-heading" id="save"> Save the script at the right place.</h4>



<p>I have named my file Annex1.py to make it easier for you to match it with this lesson on my gitHub repository dedicated to LibreOffice Tutorials.</p>



<p>Now that you have written your program, to have it available in LibreOffice you have to save it in the correct folder.<br><span style="text-decoration: underline;">For Linux:</span> <br>/home/&lt;user name&gt;/.config/libreoffice/4/user/Scripts/python<br>(to see folder ‘.config’ you need to ‘Show hidden files’ , the shortcut CTRL+h).<br><span style="text-decoration: underline;">For Windows:</span><br>C:\Users\&lt;user_name&gt;\AppData\Roaming\LibreOffice\4\Scripts\python<br><span style="text-decoration: underline;">For Mac:</span><br>(I think it’s)/Users/&lt;user name&gt;/Library/Application Support/LibreOffice/4/user\Scripts\python<br>(Please let me know in a comment if you know for sure what the folder is for Mac OS).</p>



<p>Open a new LibreOffice Calc document if you haven&#8217;t doe it yet, to check that you can run your script. And also to debug it if needed&#8230;<br>The best is to use the APSO Add-on (<a href="https://tutolibro.org/2019/07/26/libreoffice-calc-python-programming-part-1-requirements/">how to install it here</a>).<br>So if everything is ok you should find your script listed by looking in either:<br>Tool/Macros/Organize Macros/Python<br>or<br>Tool/Macros/Organize Python Scripts</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="679" height="232" src="https://tutolibro.org/wp-content/uploads/2020/03/lopy-annex1_1.png" alt="" class="wp-image-756" srcset="https://tutolibro.org/wp-content/uploads/2020/03/lopy-annex1_1.png 679w, https://tutolibro.org/wp-content/uploads/2020/03/lopy-annex1_1-300x103.png 300w" sizes="auto, (max-width: 679px) 100vw, 679px" /><figcaption class="wp-element-caption"><em>Menu Tools&gt;Macros&gt;Organize Macros&gt;Python<br>or<br>Menu Tools&gt;Macros&gt;Organize python scripts (if you have installed APSO)</em></figcaption></figure>



<p>Showing here the APSO organizer (the built-in LibreOffice one is self explanatory as well&#8230;):</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="300" height="312" src="https://tutolibro.org/wp-content/uploads/2020/03/lopy-annex1_0.png" alt="" class="wp-image-757" srcset="https://tutolibro.org/wp-content/uploads/2020/03/lopy-annex1_0.png 300w, https://tutolibro.org/wp-content/uploads/2020/03/lopy-annex1_0-288x300.png 288w" sizes="auto, (max-width: 300px) 100vw, 300px" /><figcaption class="wp-element-caption"><em>My program is saved in my usual MyPythonLibrary Module.</em></figcaption></figure></div>


<p>(Check-out my <a href="https://tutolibro.org/2019/08/16/libreoffice-calc-python-programming-part-2-hello-world/">helloworld tutorial</a> if you need more details on how and where to save your python script)</p>



<p>Try to execute your program by selecting it from the APSO organizer and click on the execute button, or from the LibreOffice organizer on the &#8216;Run&#8217; Button.<br>If everything goes write the program should write numbers 1 to 10 in column B. If not you have to debug it&#8230; or leave me a comment if you have any problem.</p>



<h4 class="wp-block-heading" id="assign">Assign your scrip to [CTRL]+0.</h4>



<p>If like me you feel that executing a python script within LibreOffice as showing previously requires too many mouse clicks you will appreciate a much quicker way to run your pythonic creations.<br>And to debug more easily your programs on the go, it is much easier also.</p>



<p class="has-text-align-left">To assign a key or a combination of keys to a python script (or to a LibreOffice Basic Macro as well) go directly in the menu Tools/Customize&#8217; </p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="333" height="160" src="https://tutolibro.org/wp-content/uploads/2020/03/lopy-annex1_3.png" alt="" class="wp-image-759" srcset="https://tutolibro.org/wp-content/uploads/2020/03/lopy-annex1_3.png 333w, https://tutolibro.org/wp-content/uploads/2020/03/lopy-annex1_3-300x144.png 300w" sizes="auto, (max-width: 333px) 100vw, 333px" /><figcaption class="wp-element-caption"><em>From Menu Tools&gt;Customize</em></figcaption></figure></div>


<p class="has-text-align-left"><br>or right click anywhere on the toolbar (not the top menu bar) and nearly at the bottom of the contextual menu select &#8216;Customize Toolbar&#8217;:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="277" height="238" src="https://tutolibro.org/wp-content/uploads/2020/03/lopy-annex1_2.png" alt="" class="wp-image-758"/><figcaption class="wp-element-caption"><em>From a right click on the toolbar</em></figcaption></figure></div>


<p>The next steps are:</p>



<ol class="wp-block-list">
<li>Select the tab &#8216;Keyboard&#8217; .</li>



<li>In the &#8216;Category&#8217; section, find and select your python module and file (in the example MyPythonLibrary/Annex1).</li>



<li>In the &#8216;Function&#8217; section select the function within the file (in the example there is only one file: write_1_to_10).</li>



<li>In the &#8216;Shortcut Keys&#8217; section select the key or combination of keys from the list, better choose one that has nothing assigned to it already (in the example Ctrl+0 : so the combination of keys &#8216;Ctrl&#8217; + &#8216;0&#8217;).</li>



<li>Click on the &#8216;Modify&#8217; button.</li>



<li>You should see the chosen keys now in the &#8216;Keys&#8217; section.</li>



<li>You should see the function&#8217;s name assigned to the Keys combination entry in the &#8216;Shortcut Keys&#8217; section.</li>



<li>Click &#8216;OK&#8217;.</li>
</ol>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="789" height="667" src="https://tutolibro.org/wp-content/uploads/2020/03/lopy-annex1_6.png" alt="" class="wp-image-762" srcset="https://tutolibro.org/wp-content/uploads/2020/03/lopy-annex1_6.png 789w, https://tutolibro.org/wp-content/uploads/2020/03/lopy-annex1_6-300x254.png 300w, https://tutolibro.org/wp-content/uploads/2020/03/lopy-annex1_6-768x649.png 768w" sizes="auto, (max-width: 789px) 100vw, 789px" /><figcaption class="wp-element-caption"><em>Assigning function write_1_to_10 to CTRL+0</em></figcaption></figure>



<p>And after emptying the cells in column B, just give a try of Ctrl+0, it should filled them again!</p>



<p>When I am testing python code, I sometimes keep that Ctrl+0 combination assigned to a function &#8216;test(*args)&#8217;, when I am happy with the function I copy/rename it to a better named one, then use the test function to code something else. You can also assign useful functions that you have built and that you use often for example to format cells in a particular way.</p>



<p>I hope you find this useful, please leave any comments to help me making this tutorial better.</p>



<p>If you like this tutorial, you could <a href="https://buymeacoffee.com/tutolibro" data-type="link" data-id="https://buymeacoffee/tutolibro" target="_blank" rel="noreferrer noopener">buy me a coffee</a> to help me continue writing add-free tutorials.</p>



<p>Thank you!</p>



<div class="wp-block-group is-content-justification-space-between is-nowrap is-layout-flex wp-container-core-group-is-layout-0dfbf163 wp-block-group-is-layout-flex">

</div>
]]></content:encoded>
					
					<wfw:commentRss>https://tutolibro.org/2020/03/11/libreoffice-calc-python-programming-annex-1-assign-a-python-macro-to-a-key/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">755</post-id>	</item>
	</channel>
</rss>
