<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Your Site's RSS Feed]]></title><description><![CDATA[The blog and portfolio of Eric Peterson, a software engineer in northern Virginia.]]></description><link>https://www.ericp.co</link><generator>GatsbyJS</generator><lastBuildDate>Mon, 20 May 2024 16:28:40 GMT</lastBuildDate><item><title><![CDATA[Why React Hooks are Great]]></title><description><![CDATA[Here’s a pretty neat example of how React hooks allow
for abstractions in really neat directions. The example use case is for a loading…]]></description><link>https://www.ericp.co/posts/why-react-hooks-are-great</link><guid isPermaLink="false">https://www.ericp.co/posts/why-react-hooks-are-great</guid><pubDate>Sun, 10 Feb 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Here’s a pretty neat example of how React hooks allow
for abstractions in really neat directions.&lt;/p&gt;
&lt;p&gt;The example use case is for a loading spinner. A good loading UX won’t show a spinner for the first second or so, because the page might load near-instantly. In that case, you don’t want to show a quick flash of a loading spinner, since that would be jarring when you could just wait a big for the screen to show. If the app or data is taking longer than one second to load, &lt;em&gt;then&lt;/em&gt; you want to show a loading spinner. And if the user has been waiting for more than &lt;em&gt;five&lt;/em&gt; seconds, the component changes the text so the user doesn’t load interest.&lt;/p&gt;
&lt;p&gt;The first file, the &lt;code class=&quot;language-text&quot;&gt;useTimeout&lt;/code&gt; hook, is very flexible. Notice that it’s used twice in the &lt;code class=&quot;language-text&quot;&gt;LoadingMessage&lt;/code&gt; component to easily give it different behavior depending on how long it’s been mounted.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// useTimeout.js&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; useEffect&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; useState &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;ms&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;isDone&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; setDone&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;useEffect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; timerId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;setDone&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ms&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;cleanup&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;clearTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timerId&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; cleanup&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; isDone&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// LoadingMessage.jsx&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; React &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; useTimeout &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./useTimeout&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;LoadingMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Don&apos;t show &apos;loading&apos; before one second, to&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// avoid flicker of loading content&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; hasBeenWaiting &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// After 5 seconds, switch text to &quot;Still loading...&quot;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; hasBeenWaitingLong &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; text &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hasBeenWaitingLong&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Still loading...&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Loading...&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;hasBeenWaiting&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here’s a &lt;a href=&quot;https://codepen.io/epeterson320/pen/pGLVLV?editors=0010&quot;&gt;working example on CodePen&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Simple and Recursive Javascript Promises]]></title><description><![CDATA[When I learned functional programming, one of the most exciting moments was the realization that recursive functions can replace all for…]]></description><link>https://www.ericp.co/posts/recursive-javascript-promises-for-the-win</link><guid isPermaLink="false">https://www.ericp.co/posts/recursive-javascript-promises-for-the-win</guid><pubDate>Tue, 28 Mar 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When I learned functional programming, one of the most exciting moments was the realization that recursive functions can replace all for- and while-loops. Being able to use recursion effectively means that you can generalize &lt;code class=&quot;language-text&quot;&gt;for&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;while&lt;/code&gt; into something simpler &lt;em&gt;and&lt;/em&gt; more powerful. Not that you always should, but this post is an example of exactly why such a thing is both powerful and practical.&lt;/p&gt;
&lt;p&gt;To start with, here’s a recursive factorial function, the “Hello World” of recursion.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;factorial&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;factorial&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It’s not too difficult to understand or write, because multiplication is instantaneous, but what if the multiplication function returned a promise, like this?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;multiplyAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;How would you write a factorial function if you had to use the above &lt;code class=&quot;language-text&quot;&gt;multiplyAsync&lt;/code&gt;? Since the multiply function returns a promise, the factorial function will have to return a Promise too. Here’s one way to do it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;factorialAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;factorialAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;n1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;multiplyAsync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This technique works for factorials, but not when order of operations matter, since it works “right-to-left”. What if we were trying to apply a list of changes to a database? Given:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Jeff&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;food&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Ice Cream&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Sonic&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;food&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Chili Dogs&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Donatello&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;food&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Pizza&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Jeff&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;food&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Cheesecake&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You would expect the fourth entry to overwrite the first. If we use the technique above, the code would expand to:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Jeff&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Cheesecake&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Donatello&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Pizza&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Sonic&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Chili Dogs&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Jeff&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Ice Cream&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Backwards.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For example, what if we were trying to insert over 9000 things into a database in groups of 500? The above method would insert the &lt;em&gt;last&lt;/em&gt; 500 things first, then the previous 500, and so on. Not very desirable behavior.&lt;/p&gt;
&lt;p&gt;So, if your database library gives you a function like&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insertRecords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;records&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// returns a promise&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;How would you write the following function?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;insertToDatabaseInBatches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;recordsToInsert&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; batchSize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// A little help?&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here’s the best I could come up with:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;insertToDatabaseInBatches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;recordsToInsert&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; batchSize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;recordsToInsert&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; batch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; recordsToInsert&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; batchSize&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; remaining &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; recordsToInsert&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;batchSize&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; db&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;insertRecords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;batch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;insertToDatabaseInBatches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;remaining&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; batchSize&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Inserting a bunch of records into a database, in batches, asynchronously, in 7 lines of code. Not bad, recursion.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Show SCN: The Better Logger I Promised]]></title><description><![CDATA[Originally posted at https://blogs.sap.com/2014/09/30/show-scn-the-better-logger-i-promised/. A month back, I wrote a short blog about the…]]></description><link>https://www.ericp.co/posts/show-scn-the-better-logger-i-promised</link><guid isPermaLink="false">https://www.ericp.co/posts/show-scn-the-better-logger-i-promised</guid><pubDate>Tue, 30 Sep 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Originally posted at &lt;a href=&quot;https://blogs.sap.com/2014/09/30/show-scn-the-better-logger-i-promised/&quot;&gt;https://blogs.sap.com/2014/09/30/show-scn-the-better-logger-i-promised/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A month back, I wrote a short blog about the application log, and how great it would be to have yet another object oriented wrapper around the SBAL function group and friends.  Well, I wasn’t kidding.  I just put up a working version on Github, and added some documentation to explain some of the features I thought would make a logger tool great.  It’s been done fifty times before, but I haven’t seen any of them with the features I describe.  It’s all working, so feel free to kick the tires, fork the project, and please, please, let me know what you think!&lt;/p&gt;
&lt;p&gt;epeterson320/ABAP-Logger · GitHub&lt;/p&gt;
&lt;p&gt;Here is my original post: What Would a Developer-Friendly Application Log Look Like?&lt;/p&gt;
&lt;p&gt;Below is most of the readme from Github:&lt;/p&gt;
&lt;h2&gt;ZCL_LOGGER&lt;/h2&gt;
&lt;p&gt;SAP Logging as painless as any other language&lt;/p&gt;
&lt;p&gt;One of these things is not like the others
One of the most effective ways of debugging and inspecting a program’s operations is by writing to a log.  Logging is so powerful, just about every language has some way of doing it.  For example, if you want to write to a log in javascript, you just need to write the following line of code:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;“Leapin’ lizards&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; something went wrong&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;”&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or how about in Ruby? Ruby has the added benefit of different levels of messages.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;require&lt;/span&gt; ‘logger’
log &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;‘logfile&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;log’&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;warn&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;“You’re on thin ice&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; bud&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;”&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;info&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;“Things are normal again&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;”&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Writing an Android app? You’re in luck – you can log and optionally tag messages, all in one line of Java.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;‘&lt;span class=&quot;token constant&quot;&gt;MAPS_INTERFACE&lt;/span&gt;’&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ‘&lt;span class=&quot;token class-name&quot;&gt;The&lt;/span&gt; system is down&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;’&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So, how does ABAP logging stack up to the other languages? What code is required to log a string to be viewed later?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;abap&quot;&gt;&lt;pre class=&quot;language-abap&quot;&gt;&lt;code class=&quot;language-abap&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;DATA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TYPE&lt;/span&gt; bal_s_log&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;handle&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TYPE&lt;/span&gt; balloghndl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        handles_to_save &lt;span class=&quot;token keyword&quot;&gt;TYPE&lt;/span&gt; bal_t_logh&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

header&lt;span class=&quot;token token-operator punctuation&quot;&gt;-&lt;/span&gt;object &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘ZINTERFACES’&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
header&lt;span class=&quot;token token-operator punctuation&quot;&gt;-&lt;/span&gt;subobject &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘ACCOUNTING’&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
header&lt;span class=&quot;token token-operator punctuation&quot;&gt;-&lt;/span&gt;extnumber &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘Stuff imported &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;legacy&lt;/span&gt; systems’&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;CALL&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;FUNCTION&lt;/span&gt; ‘BAL_LOG_CREATE’
    &lt;span class=&quot;token keyword&quot;&gt;EXPORTING&lt;/span&gt;
    i_s_log      &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;header&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;IMPORTING&lt;/span&gt;
    e_log_handle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;CALL&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;FUNCTION&lt;/span&gt; ‘BAL_LOG_MSG_ADD_FREE_TEXT’
    &lt;span class=&quot;token keyword&quot;&gt;EXPORTING&lt;/span&gt;
    i_log_handle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;handle&lt;/span&gt;
    i_msgty &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘E’
    i_text &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘You see&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; what had happened was…’&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;CALL&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;FUNCTION&lt;/span&gt; ‘BAL_DB_SAVE’
    &lt;span class=&quot;token keyword&quot;&gt;EXPORTING&lt;/span&gt;
    i_t_log_handle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; handles_to_save&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you’re not asleep after writing all that, then you’ve at least forgot what you were programming before you had to write to a log.  If anything, logging should be QUICK so you can get on with the real programming!&lt;/p&gt;
&lt;h3&gt;Get out of my way&lt;/h3&gt;
&lt;p&gt;A better log would barely interrupt my code, so I can output messages in one line, and you don’t lose the big picture as you are reading it. What do you wish the ABAP example above looked like?  How about this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;abap&quot;&gt;&lt;pre class=&quot;language-abap&quot;&gt;&lt;code class=&quot;language-abap&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;DATA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TYPE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;REF&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TO&lt;/span&gt; zcl_logger&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; zcl_logger&lt;span class=&quot;token token-operator punctuation&quot;&gt;=&gt;&lt;/span&gt;new&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘ZINTERFACES’
                        subobject &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘ACCOUNTING’
                        desc &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘Stuff imported &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;legacy&lt;/span&gt; systems’ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

log&lt;span class=&quot;token token-operator punctuation&quot;&gt;-&gt;&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; ‘You see&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; what had happened was…’ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All the information, none of the boilerplate. This is the goal of ZCL_LOGGER.&lt;/p&gt;
&lt;h3&gt;Log anything&lt;/h3&gt;
&lt;p&gt;Making use of SAP’s run-time type services, we can pass almost anything we might want to log to an instance of ZCL_LOGGER, and it will do the heavy lifting.&lt;/p&gt;
&lt;p&gt;Log a string!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;abap&quot;&gt;&lt;pre class=&quot;language-abap&quot;&gt;&lt;code class=&quot;language-abap&quot;&gt;log&lt;span class=&quot;token token-operator punctuation&quot;&gt;-&gt;&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; ‘Document &lt;span class=&quot;token number&quot;&gt;4800095710&lt;/span&gt; created successfully’ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Log a bapi return message!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;abap&quot;&gt;&lt;pre class=&quot;language-abap&quot;&gt;&lt;code class=&quot;language-abap&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;DATA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; rtn &lt;span class=&quot;token keyword&quot;&gt;TYPE&lt;/span&gt; bapiret2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
log&lt;span class=&quot;token token-operator punctuation&quot;&gt;-&gt;&lt;/span&gt;add&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; rtn &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Log a…gasp…TABLE of bapi return messages!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;abap&quot;&gt;&lt;pre class=&quot;language-abap&quot;&gt;&lt;code class=&quot;language-abap&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;DATA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; msgs &lt;span class=&quot;token keyword&quot;&gt;TYPE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;OF&lt;/span&gt; bapiret2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
log&lt;span class=&quot;token token-operator punctuation&quot;&gt;-&gt;&lt;/span&gt;add&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; msgs &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Log an exception? Yep!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;abap&quot;&gt;&lt;pre class=&quot;language-abap&quot;&gt;&lt;code class=&quot;language-abap&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;TRY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    rubber_band_powered_spaceship&lt;span class=&quot;token token-operator punctuation&quot;&gt;=&gt;&lt;/span&gt;fly_to&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; the_moon &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;CATCH&lt;/span&gt; zcx_not_enough_power &lt;span class=&quot;token keyword&quot;&gt;INTO&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    log&lt;span class=&quot;token token-operator punctuation&quot;&gt;-&gt;&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; err &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;ENDTRY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Log the current system message.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;abap&quot;&gt;&lt;pre class=&quot;language-abap&quot;&gt;&lt;code class=&quot;language-abap&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;MESSAGE&lt;/span&gt; e001&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;oo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;WITH&lt;/span&gt; foo bar baz &lt;span class=&quot;token keyword&quot;&gt;INTO&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;dummy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
log&lt;span class=&quot;token token-operator punctuation&quot;&gt;-&gt;&lt;/span&gt;add&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; “you don’t even need &lt;span class=&quot;token keyword&quot;&gt;to&lt;/span&gt; pass anything &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; bro&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Log the return of a BDC call.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;abap&quot;&gt;&lt;pre class=&quot;language-abap&quot;&gt;&lt;code class=&quot;language-abap&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;CALL&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TRANSACTION&lt;/span&gt; ‘CO07’ &lt;span class=&quot;token keyword&quot;&gt;USING&lt;/span&gt; bdc_tab &lt;span class=&quot;token keyword&quot;&gt;MESSAGES&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;INTO&lt;/span&gt; bdc_messages&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
log&lt;span class=&quot;token token-operator punctuation&quot;&gt;-&gt;&lt;/span&gt;add&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; bdc_messages &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And that’s every scenario I’ve been able to think of, so far.&lt;/p&gt;
&lt;h3&gt;Don’t Ignore SAP’s Strengths&lt;/h3&gt;
&lt;p&gt;As frustrating as it can sometimes be, the SAP environment has a lot of power, and it would be good not to ignore it.  Transaction code SLG1 views and filters logs with ease, and it allows for added context variables and parameters. A new logger class should not reinvent the wheel, the wheelbarrow, or the mechanisms for saving and displaying logs.&lt;/p&gt;
&lt;p&gt;If you have an instance of a log object, you can add context variables and a problem class, two of a few things that SLG1 handles well.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;abap&quot;&gt;&lt;pre class=&quot;language-abap&quot;&gt;&lt;code class=&quot;language-abap&quot;&gt;log&lt;span class=&quot;token token-operator punctuation&quot;&gt;-&gt;&lt;/span&gt;w&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; obj_to_log &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘Document created &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;errors&lt;/span&gt;’ “&amp;lt;– Which document? Needs &lt;span class=&quot;token keyword&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; new_document &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; “&amp;lt;– Here’s the &lt;span class=&quot;token keyword&quot;&gt;context&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since this log is designed to be simple, it has compromised a lot of the more exotic function modules in the SBAL family. If your log needs to use one of these function modules, the log header, handle and database id are all read-only members of the class, so you can pass them right along to the function module.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;abap&quot;&gt;&lt;pre class=&quot;language-abap&quot;&gt;&lt;code class=&quot;language-abap&quot;&gt;log&lt;span class=&quot;token token-operator punctuation&quot;&gt;-&gt;&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; ‘Results &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; system &lt;span class=&quot;token keyword&quot;&gt;analysis&lt;/span&gt;’ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;CALL&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;FUNCTION&lt;/span&gt; ‘BAL_LOG_MSG_CUMULATE’
    &lt;span class=&quot;token keyword&quot;&gt;EXPORTING&lt;/span&gt;
    i_log_handle &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; log&lt;span class=&quot;token token-operator punctuation&quot;&gt;-&gt;&lt;/span&gt;handle
    i_s_msg &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; l_msg
    i_compare_attributes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; abap_true&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Chainable&lt;/h3&gt;
&lt;p&gt;It’s 2014, so yes, you can chain method calls.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;abap&quot;&gt;&lt;pre class=&quot;language-abap&quot;&gt;&lt;code class=&quot;language-abap&quot;&gt;zcl_logger&lt;span class=&quot;token token-operator punctuation&quot;&gt;=&gt;&lt;/span&gt;new&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘foo’ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;-&gt;e&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; ‘Bad things happened&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; See details’ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;-&gt;e&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; error &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[What Would a Developer-Friendly Application Log Look Like?]]></title><description><![CDATA[Originally posted at https://blogs.sap.com/2014/07/30/what-would-a-developer-friendly-application-log-look-like/. 9/30/14 UPDATE: I’ve begun…]]></description><link>https://www.ericp.co/posts/what-would-a-developer-friendly-application-log-look-like</link><guid isPermaLink="false">https://www.ericp.co/posts/what-would-a-developer-friendly-application-log-look-like</guid><pubDate>Wed, 30 Jul 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Originally posted at &lt;a href=&quot;https://blogs.sap.com/2014/07/30/what-would-a-developer-friendly-application-log-look-like/&quot;&gt;https://blogs.sap.com/2014/07/30/what-would-a-developer-friendly-application-log-look-like/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;9/30/14 UPDATE: I’ve begun work on a tool like I describe here.  It’s detailed in this post: Show SCN: The better logger I promised&lt;/p&gt;
&lt;p&gt;Do you ever have this problem?  You’re in the middle of writing a fantastic ABAP program.  It hums, it purrs, it looks reeeeally good.  The code is so clean uncle Bob would be proud.  You use the best design patterns and your application is modularized well.  Then you realize you need to log a few lines of text to view later in SLG1.  Your heart sinks.  Your robust, clean application is about to become polluted by countless 10-line calls to FM ‘BAL&lt;em&gt;LOG&lt;/em&gt;CREATE’ and its fellow hoodlums, all because you wanted to save the output of a BAPI you called.  First world problems, AMIRITE?  Anyone?&lt;/p&gt;
&lt;p&gt;The obvious solution is to put an object-oriented wrapper around these functions.  This solution is so obvious, in fact, that every department in SAP has written their own verison of it, and my company has added two more.  This is consistent with SAP’s approach to developer tools: Quantity Guaranteed.&lt;/p&gt;
&lt;p&gt;So why do we need another OO wrapper?  Well, because I believe in the power of collaboration, for one.  None of the other logs have been designed by the developer community.  Another reason is that logs have come a long way since 1999, when SAP released their function modules for the application log, and developers are used to a more concise syntax.  For instance, if I want to write to the console in javascript, it’s:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;‘The System is Down’&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;but in SAP, I have to declare 2 variables, then spend a page of code calling function modules BAL&lt;em&gt;LOG&lt;/em&gt;CREATE, BAL&lt;em&gt;LOG&lt;/em&gt;MSG&lt;em&gt;ADD, and BAL&lt;/em&gt;DB_SAVE.  Part of the reason is that SAP has multiple logs, while a web browser only logs messages in one console.  So when you log anything in SAP, it must go to a specific application log object and sub-object.  Android (java) also writes to multiple logs.  Its logs are called with two arguments, tag and message, like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;“&lt;span class=&quot;token class-name&quot;&gt;SystemMsgs&lt;/span&gt;”&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; “&lt;span class=&quot;token class-name&quot;&gt;The&lt;/span&gt; system is &lt;span class=&quot;token class-name&quot;&gt;Down&lt;/span&gt;”&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If logging in ABAP was going to be just as awesome (and I know it can be), what would it look like?  Please post your ideas and discuss!  Once enough good ideas are gathered, I’d like to start building something on github.  Anyone is welcome to contribute code or just ideas and insights.  Here’s an example what I think would make a good application log API:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;abap&quot;&gt;&lt;pre class=&quot;language-abap&quot;&gt;&lt;code class=&quot;language-abap&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; zcl_app_log&lt;span class=&quot;token token-operator punctuation&quot;&gt;=&gt;&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘ZFICO’ subobject &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘INTERFACES’ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;TRY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    zcl_accounting&lt;span class=&quot;token token-operator punctuation&quot;&gt;=&gt;&lt;/span&gt;do_some_important_upload&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    log&lt;span class=&quot;token token-operator punctuation&quot;&gt;-&gt;&lt;/span&gt;add&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; ‘The &lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; has finished’ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;CATCH&lt;/span&gt; zcx_upload_failed &lt;span class=&quot;token keyword&quot;&gt;INTO&lt;/span&gt; err&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    log&lt;span class=&quot;token token-operator punctuation&quot;&gt;-&gt;&lt;/span&gt;add&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; err &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;ENDTRY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Best Practices for Users to Maintain a Z-Table]]></title><description><![CDATA[Originally posted at https://blogs.sap.com/2013/10/01/best-practices-for-users-to-maintain-a-z-table/  UI design is one of the most exciting…]]></description><link>https://www.ericp.co/posts/best-practices-for-users-to-maintain-a-z-table</link><guid isPermaLink="false">https://www.ericp.co/posts/best-practices-for-users-to-maintain-a-z-table</guid><pubDate>Tue, 01 Oct 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Originally posted at &lt;a href=&quot;https://blogs.sap.com/2013/10/01/best-practices-for-users-to-maintain-a-z-table/&quot;&gt;https://blogs.sap.com/2013/10/01/best-practices-for-users-to-maintain-a-z-table/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 150px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4ef923403e484251b1818ca9feef082e/8a4e8/computer.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 90.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAAsSAAALEgHS3X78AAAEZUlEQVQ4y4VUa0xURxT+7t01hcbUmCZNTEGboMQXIYItwoppgBKh3ScIe1fYKmRddtldUGDdwK5gRVOqPKq0PBSqpSFpTFsblWJKxUdRCqRWRSDaQn8gtT+aFmNfLHdO5y5tf9SmneRkzuTMfHPO+b4Z4B/D6/WioKAg5BMRZG52u6PXZiu6//RS9ZK1a5Zj7do1ghKTJAn/OxISEhAbG4uyst2qxsajfPZZDPoM2vTCanK599S3tL6H5uZm1cDAANatW/ffYN3d3WhqakJkZISgrDetQrjFuvsb367F1FEDOUO7PVhesmO1o8iO9JfSRGWPyWT6dzDGGKKjo2Gz2RRQdefJj1BeXrlv69ZkuncGQbqJoDFzJe1yeE+f6Z3BnbGJEGB6ejpkWX4cUAkoIzExQZDM21Di0K3IkeyPDrh5K8d5K8dE9n4dZK3BTD5vSUpNzQHk5+eplDPx8fGPA8bFxYXmwcEhVU/fJDylVad0mTH00yWe3Q2R5CHOww3MWwzPksNVeV0hRTFlpKamIhgMPg5msUiqQCAAX0WxRm/Ko3f2g9Fdgc0NggW/4P6EyK6e4KVnZZO/qtLa0tIBn2+vatmyZYiKiloAm52dhcfj+UsmITnYnb6rkiGC6Eue3YhAbBhsfgjs12ugyXOQrVlLyV0amOJHwpVzYWFhwvT0NPR6PZCZmQmNRsNv8qqOHm1Tbsx7+RUd9bVysAmRfrsOJg/zuyZBX58De2qJigJ2zOVv15I/UOs/e74fnZ0n1E6nk/c/EWhvb8eK5ZEhmWjW4MlXC/dMObcvJhrDPI2AfugHe40Tc6kDtNMI9vwGsAcXIfuLniCnZ9/DXENcxJbkTdi4MT6EAZfLxYV6TH2q62P+Svw1GRlbaPwDzNEoz+4a79sd0MXjoJQkKAwoxryFIk2dxZzJkEYHDx05fv/B75iYGFeFSNq8OUm05ptR6tQ9l2Nx/FzrDpUnz17hYKNgjwZAP14GnW5YAKwoBHNIPPYVz7wYrLgkQLvd+fHFxQ5kZGwVcfPWbVVv/zSXSaArSxujSCNYsVOkuj1gv1wHaVNAVj0oaQNIrQb1vA1q2MsBx0Wa6UUw25hIdYePffKnjARUV1ejosydnJ1jpQYv5B0GgSllxawCvVkF6m/n+0ZBpnRQa4D7t0N95brkoPcE1liO+WJPJdUEynVNTY0LP4qtqPLz/KwImjyPYFi4QIIAFh0Fmurh4WmQJw/U6OX+XVBwkM+crJAuR0R6eAXz2br1dLi+9VaIFL+/2pq9zUhDXVwm36np2wsCS9GIdKBUpOkLIgcUab9LpL62BV8hiz9DUkqmUYHRzCL6sB5BT2kFNdS/4YIlz/59+uZFNHgS8mctoKF3wYxpCwSsXwka7gId4kS9XsJjpzjjrVxCbX8bu9wO9ulbYC8mPUO1B4/MQqvVjufm5pLBJMl6o5npjRLl5krEP08ymyXSGRbWiik+30fKHsUModnMlLOSZCb+Md/6A2MCY5NzLHGaAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Warning sign of man tripping on computer&quot;
        title=&quot;Warning sign of man tripping on computer&quot;
        src=&quot;/static/4ef923403e484251b1818ca9feef082e/8a4e8/computer.png&quot;
        srcset=&quot;/static/4ef923403e484251b1818ca9feef082e/8a4e8/computer.png 150w&quot;
        sizes=&quot;(max-width: 150px) 100vw, 150px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;UI design is one of the most exciting parts about my job as a developer.  It is art, programming, and psychology at the same time.  A few weeks ago I had the requirement to create a table maintenance program for our business users to maintain a large custom database table.  A few administrators were then going to add, modify and delete entries in this custom table that would in turn be used by other background programs.  Sounds simple, I thought.  It wasn’t.  I learned a lot about creating a table maintenance dialog, not the least of which was how to spell “maintenance” correctly.  I wanted to summarize a few things I learned from this adventure.&lt;/p&gt;
&lt;p&gt;Bad Doctors, T.V. Writers and User Interfaces
The television show The Walking Dead is getting ready to premiere its fourth season and has the highest viewership among any cable TV show in the U.S.  It also received much criticism for being very slow-moving and having “filler episodes” some weeks with little to no action.  “Our heroes should be fighting off more zombies and rescuing other survivors in the post-apocalyptic world,” said the fans.  But the writers knew better.  An hour of baseball bats and machine guns and blood n’ guts every week would get old quickly.  So the writers added complex father-son relationships, outcasts trying to find their place, and familiar love triangles set amidst an extreme environment.  As a result, people kept watching.&lt;/p&gt;
&lt;p&gt;Likewise, If I went to the doctor and he or she said “I’m not sure what to prescribe, let me know what medicine you want and I’ll give that to you,” I’d run out of the clinic as fast as possible.  Actually I might steal all the tongue depressors on the way out, because I’m never returning to that doctor, and tongue depressors intrigue me.&lt;/p&gt;
&lt;p&gt;What’s the point of these examples?  I’m trying to show that the consumer often doesn’t know what they want.  I’m not going to crowdsource medical advice, and neither will I give the user the interface they tell me they want.  I’m going to tell him or her what’s best, because I’m a designer/developer and they don’t know the appropriate time to use a radiobutton vs. a checkbox, let alone design the screen layout and flow for a program they need.&lt;/p&gt;
&lt;p&gt;Certainly you, the developer, need to listen closely to the user’s needs (and to any functional analyst) but the technical details of the final application, including UI “feel,” ought to be your responsibility.  Users and functional types may strongly disagree with your UI choices, so it is important to communicate as clearly and effectively as possible.  You must convince them why their UI is the wrong choice.  In this age of agile development, it’s not a good excuse to say “But I gave you exactly what the design spec asked for!” when the user whines about your program.&lt;/p&gt;
&lt;p&gt;If you give the user exactly what they want, they’ll likely be back every month wanting some little change in the program.  If you seek to understand their need and argue well for a better (read: more standard) UI, they will be very pleased with the final result, and the program will require less maintenance over its lifecycle.&lt;/p&gt;
&lt;p&gt;Users and Z-Tables
Now that I’ve got that rant out of the way, one of the toughest UI challenges for me was creating a table maintenance dialog.  TMD’s, as I’ll call them, are programs with a very simple task that are very complicated “under the hood.”  I’ve compiled nine tips and tricks about how to create one well.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;This is 5% Table and 95% User
Any database table can be maintained by only the four CRUD operations (create, read, update, and delete).  So, how difficult can it be to put a front end on four different database operations?  Not difficult, if you’re okay with annoying everyone in your company, filling the database with bad data, and all-around mediocrity in your life.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you want to implement a good table maintenance dialog, however, you need to worry about security, data validation, message handling, view restrictions, and more.  Users (at least the human ones) will do everything they can to screw up and misuse a program.  Some may be downright evil.  As said in a 2008 commentary about Craigslist spammers, “When you fail to design for evil, you have failed your community.”&lt;/p&gt;
&lt;p&gt;Most TMD design requirements will fall into one of two categories:&lt;/p&gt;
&lt;p&gt;Getting the correct slice of data FROM the database to the user’s display.
Making sure only good user input goes INTO the database.&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Use SAP’s Table Maintenance Generator
The good news is, the bulk of a good table maintenance dialog will be built by SAP.  This may seem painfully obvious to some, but when I got the requirement to build a table maintenance dialog I was told, “We’ve done this for another Z-table before; here is a program for you to copy.”  The program was a module pool with 1300 lines of code, 7 dynpro screens, and five GUI statuses.  All to create, read, change, and delete entries from one database table!  I would not let that program near children.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you didn’t know, SAP transaction SM30 allows end-users to maintain database tables directly.  It’s far prettier than any dialog you have time to create, and you can use the ABAP dictionary to integrate your custom table into this transaction.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 555px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a5f913316e84b6ec87d0822d3d7c94fe/cd039/tmd.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 94.47852760736197%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAIAAAAf7rriAAAACXBIWXMAAAsSAAALEgHS3X78AAAC+UlEQVQ4y6WSSXPaWBSF9eN73ctedVWqV3GwK7FNORiwScwkJmGEhAYQCKF5fJMQTjqLXInCy9606tSR6uoO37sSZzio/jz92pk8vszbfbHxMr9t9lv9ZXsgtQfLh8602X393Og9fJvWn0aN70KrL963+PrTWN4GnLB2Pz0J18+vd33lrideNYa1tnDV7n1sdT+/LOpDFXTXk8DvBzL415F+35e/dKWx7nGGE41W1kjxeNkVdLs3EceSPVgq3bk8kvcrmyg2VR2mebnmMtWh4JrHFIeZAeMWmnXTHD68CPXvs1qjX2sMao3uTZOvfxPuOpMWLw2Wu564aw5XT2OtM9MfB1Jnqjd5mRc1TjP2yuZgB0g3XX4m9vjZbKFI6tZ0IsP0/vr70x9/fqhd30+FV1nbSqoxmLwKks7P5nNpxSlrE5SQ3E+wst4JomxYDj39m7FTEONub/r4PJxMpvbh4LmeYVqQs9K3srbzg4zTNnvoGaTkXDwWFqphprRIcB4hFoZhHIV+EDquZ9s2FEuaIWuGuFoDGqduzPlSDVPixXi2ALS9G2VlMTmGGTWtw35vgVuHg+3Y6+1e1o2lupHUTZzgEltUNjHOYTh03ZgH24+BGepjzDw/9Hy4Atcr76bl6LsDoOmGRTArsfduDKkACeRelILDWBB0BKIwI9AXFFZHCyAnRmFKMclh2xYAZ6yIcJ7QIqPFmflcDJ6VCMf3h4ooR/kbIUcOANwIoSoES0rJ8V3JJVK9KiMxys+O6InAZH37P4rhJ3EiBEiAfeZ8V3yJVK/KSITys8NGKT2Wxf81meTVUS9dEDv3KoMp4WBwkFJYQFqtClq+q4yQakmkoPkbCMPA/A2V8ZMfZVyYID9CQXxR9TFKxaW7fmraYRAhDBtGDIQxi2Jse0mUYo7kpxhgKubyl8xoglmCaAqOwcuDAHxSkrP4kgbCrOBY8QOxE85PtPjphtl4WMPe7XLyj6XVkHubpB4+/oJe6521hQNCv+In5IPo8cdvnb3vJL7FVyEAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Table maintenance dialog screenshot&quot;
        title=&quot;Table maintenance dialog screenshot&quot;
        src=&quot;/static/a5f913316e84b6ec87d0822d3d7c94fe/cd039/tmd.png&quot;
        srcset=&quot;/static/a5f913316e84b6ec87d0822d3d7c94fe/222b7/tmd.png 163w,
/static/a5f913316e84b6ec87d0822d3d7c94fe/ff46a/tmd.png 325w,
/static/a5f913316e84b6ec87d0822d3d7c94fe/cd039/tmd.png 555w&quot;
        sizes=&quot;(max-width: 555px) 100vw, 555px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Isn’t it (comparatively) pretty?&lt;/p&gt;
&lt;p&gt;Table maintenance dialogs are deceptively complex.  To keep the amount of code you need to write under control, stay as close to SAP standard as possible.  To save you and your coworkers many headaches, generate a table maintenance dialog the standard way.  If you don’t know how, here’s the documentation.&lt;/p&gt;
&lt;p&gt;SAP Library – Create a Table Maintenance Dialog.&lt;/p&gt;
&lt;p&gt;Now you’ve got a program that allows users to maintain a table.  And you wrote zero lines of code!  You must be an amazing programmer.  You can maintain the table via SM30 (Call View Maintenance) now.&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Use a Custom Transaction Instead of SM30
At my company, end users do not have access to transaction SM30.  That was the justification given to me when I asked about another custom table maintenance dialog for a different Z-Table (In all fairness, this reinvented wheel was only 300 lines of code and three dynpros).  Instead of using transaction SM30 to maintain a table, there are two better ways to use the table maintenance dialog, and you won’t have to create any dynpro screens.  Have I mentioned I hate dynpros?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Parameter Transaction: Requires no ABAP.  From SE93, create a new transaction.  When prompted for the type, choose “parameter transaction.”  Set SM30 as the default transaction and check “skip initial screen.”  This works great for tables that won’t have many entries – my rule of thumb is fifty or less.&lt;/p&gt;
&lt;p&gt;Add the following default values:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;UPDATE&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VIEWNAME&lt;/td&gt;
&lt;td&gt;(name of your Z-Table)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;ABAP Report: Easier to customize.  Build a custom report and call function module “VIEW&lt;em&gt;MAINTENANCE&lt;/em&gt;CALL”.  This requires maintenance of a custom report, but it has all the flexibility of an ABAP program.  This is a big advantage if you want to add a selection screen or build the TMD into another application.&lt;/p&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;Widen the Overview Window for Tables With 5-10 Fields.
Making your users scroll horizontally is as annoying as websites that automatically play music or game invitations from distant friends on Facebook.  If you have more than 4 fields in the table, this is essential!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 181px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/110ab5f37d92db6106821da9f0507c0f/bcd8a/candy.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 96.93251533742333%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAATABQDASIAAhEBAxEB/8QAGQABAAIDAAAAAAAAAAAAAAAAAAMEAQIF/8QAFwEAAwEAAAAAAAAAAAAAAAAAAAIDBP/aAAwDAQACEAMQAAABjuQWUDZnOXgecgkv/8QAGhAAAgMBAQAAAAAAAAAAAAAAAQIAERMhMv/aAAgBAQABBQJVs5ACnEVgsL80jerMUmv/xAAaEQABBQEAAAAAAAAAAAAAAAABAAIDEBIh/9oACAEDAQE/AWRgdW7/AP/EABkRAQACAwAAAAAAAAAAAAAAAAEAAhARMf/aAAgBAgEBPwFuvZvDP//EABsQAAIBBQAAAAAAAAAAAAAAAAABEBESQVHh/9oACAEBAAY/AkVuOj2Yhz//xAAbEAACAwEBAQAAAAAAAAAAAAAAAREhQWExcf/aAAgBAQABPyGAY9EogrYPMpjgUI6DXlOnFlPsSazQP//aAAwDAQACAAMAAAAQXyh+/8QAGxEBAAICAwAAAAAAAAAAAAAAAQARITFhofD/2gAIAQMBAT8QMUl8+7jluWx3P//EABoRAAICAwAAAAAAAAAAAAAAAAABESFBsdH/2gAIAQIBAT8QRRQrjfRiKT//xAAbEAEAAwEBAQEAAAAAAAAAAAABABEhMUFRof/aAAgBAQABPxDfaSsXUEIKaGu1z3YrWQcQD9INxnpyBSwoY8gADH6wgTkNwWHy4Kluz//Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Candy crush character&quot;
        title=&quot;Candy crush character&quot;
        src=&quot;/static/110ab5f37d92db6106821da9f0507c0f/bcd8a/candy.jpg&quot;
        srcset=&quot;/static/110ab5f37d92db6106821da9f0507c0f/d2f63/candy.jpg 163w,
/static/110ab5f37d92db6106821da9f0507c0f/bcd8a/candy.jpg 181w&quot;
        sizes=&quot;(max-width: 181px) 100vw, 181px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Rule of thumb: Be less annoying than this.&lt;/p&gt;
&lt;p&gt;To change the standard screen:&lt;/p&gt;
&lt;p&gt;From SE11 (ABAP Dictionary), open the screen to modify your Z-Table.  On the menu, choose Utilities -&gt;Table Maintenance Generator.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 310px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/62008f042e1ffe77f2fcbf989dad8547/5fad2/screen1.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 107.36196319018406%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAIAAADJt1n/AAAACXBIWXMAAA7DAAAOwwHHb6hkAAADGUlEQVQ4y4VUWY/cNgzW3y0atMlD0Ke2/ytJu0iCdLEodhZZj29btmVb8n3Lt63QM5tgCzQt8YGgSFHiJSGWdZLJTjJ5NOjZYDRpfFYCOr4kRYdJFkQVoQXwbljjrHWDnMY1H9aAVYil9d2j+/He+nSy/pZJXvEwKiwv6oepanvToYSmXpgGLFvWLc5qHVMaFyB7NEUNH4UQGGPDNHTDGMZJXGjd93XbxTP6ttj3QwxYjsZ5BTW+UEgp8bwsy9I0bZrmuWdZlmmSMHoQYxH450WDkpKDzfd9cAaDoigXM4Pd10uu98Ay+EphGG7r0vQLur0/gw12n89nXdfF/9H1LN61OMyRm3SwaNuuKMq2423Lu+4JQH0/1HUN1mVZn/kfnOYcKZoCUlEUOSTRNHAEABwgzjzPq6oCoef9MAzjOPYHwYk9uHjQKpoUcBQEDNlCOpqmQfyqqkIVFEWVJCkvCtgKeWqXPWAyTHOZp6TqEfYjsBHfd1wXO26cJJ5HIGBQbht0a1vXDWIGDssDlxKC0PIJOUF8xOB5GNuO40DlTNOE266F+X7ZtrLpEYnyI3tKLcu6Otu27fvBsiz/Ue2e87hoUTdMYl9d14EBcx0cR+wsPSZJ/M/R2r4BBu/SqqasW5TVR3ohTR03ZHEeJYWFCY2ysuZV0+dV14//EgLkXLUjkk1LbIxYd8rD25iciHnr6p8s+T1WP0bevSHdABcz3QdfjMEV+xCIJQjiCFHnRji/0LvX2ruf3A8vlTcv8IeX+P3PwV+v9D9+NP98ob79Ibp7JZzfdutXYR/Y7d8Ffp14b1Bel3AzdR/kh5s0lGz1Fqu3aXheeTC3ZO4A/taHYmZiYk98iYbKKjIPhcnxejzCNN2O09IPIhJEaV6vmwAsV76KYdrGeRumFQAC7xcWhch0yOVVEV3XCPEsywQ42B7HYd9WeD3LMkNXwzDQVEWWJVmG96Oty0zCGH6SCpwjxhyMockwR5debt/p8JNpmsai6pBF4qYbVQOfPp9Pn6WAxtAhGD1QAqpmAE2cFA1o+FiDkk91e1HmzRcrV44MUJM2XQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Selection screen screenshot 1&quot;
        title=&quot;Selection screen screenshot 1&quot;
        src=&quot;/static/62008f042e1ffe77f2fcbf989dad8547/5fad2/screen1.png&quot;
        srcset=&quot;/static/62008f042e1ffe77f2fcbf989dad8547/222b7/screen1.png 163w,
/static/62008f042e1ffe77f2fcbf989dad8547/5fad2/screen1.png 310w&quot;
        sizes=&quot;(max-width: 310px) 100vw, 310px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;From the menu, choose Environment -&gt; Modification -&gt; Maintenance Screens and select the screen you want to change.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 529px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c761e3e76fdc90c904766513742a4fe5/67d6a/screen2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 49.079754601226995%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsSAAALEgHS3X78AAABNUlEQVQoz5XO207CQBAG4H0+Y/QJTDxwg4m3Jh54INTEGIQ7K4LeQGhjT9BSlkKssKXd7rZdWpULt4jRkHgg+TL5J5mZDMgVrndPyrlCZe+0zG0flXaOS1uHV+v5s43985+s5S82D4pAaOp12arK3aps1VR43x7ODeranL5Q0+wvCtQtR7NG4E42Hsz+rWkLhl3vPzfdsOGGzU8NROeBtrxY9FkGT0VEfBoGUQLk1qMiShD2O+3OwB52DdM0TNiDPHCqonJtTfcmXuBjjuDARe7YIwhH4AlhHE49ynxew6xm6EdgeNHygfg7EiXIj4DjBpS98B9+R+J0SbY8mlAap38uL9+KkrFHgYMCEif8vZVQNnNJCiaEsddZlL79V8LNnHEPGipoSLqkdER5BZJiCtXLm0rxHZeoBH0CN0vJAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Selection screen screenshot 2&quot;
        title=&quot;Selection screen screenshot 2&quot;
        src=&quot;/static/c761e3e76fdc90c904766513742a4fe5/67d6a/screen2.png&quot;
        srcset=&quot;/static/c761e3e76fdc90c904766513742a4fe5/222b7/screen2.png 163w,
/static/c761e3e76fdc90c904766513742a4fe5/ff46a/screen2.png 325w,
/static/c761e3e76fdc90c904766513742a4fe5/67d6a/screen2.png 529w&quot;
        sizes=&quot;(max-width: 529px) 100vw, 529px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To widen the overview window, click “Layout” and simply drag the side of the table control to widen it.  If there are a great many fields, you may not be able to fit all of them on the screen.  Your users would have to scroll horizontally, and now would be appropriate for you to shed a tear.  Save and activate the screen.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 650px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4704b31edd7770b426907655ea535aef/9d76a/dragscreen.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 85.88957055214723%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAIAAABSJhvpAAAACXBIWXMAAAsSAAALEgHS3X78AAABcUlEQVQ4y82Sy07CQBSGeWnjxhhbgm58BY0hqAiowVjolbZcSju0004LtKCE4OUNIOEi4CmYLtQF3RiTM38688+XvzlzEnW18rOqsrgpoaZK8FFTpMiSRW5zKNwVcglJYPWG2myossiqMg+njaqCTQMZmgWrpigSV1UEtcLLEqdWOFC4wzDF49RJApg2MT3SAu24lue0+kF7vV4vFgvQ97eRa6PIAoXtU+DeF3JJKgnJZYKNbYFBLN3vkNlsNh6P5/P5aPjsmM2t5Vih2mYz6Ni57BV9RH+HnRB2AZtMJhA+Gg7s3+B89jo+jAHWg66Tv4kN62FyS+vZKH+ZoandYWw4GHlI80oPA5m/TV9QdDIObKOuWG6zj4GHbzPp1MFhnN82dZ8pehzTw0bx/Ox0b3/3ZOSAIs3W64FPvhom8iWC9RgNg25HTyULLIyO6yBQmCSwe773sVxOp9PVavX6MgQyskBh2/dJIUym/nJI/gv8CZSTL9YjWQSEAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Screenshot of dragging the table wider&quot;
        title=&quot;Screenshot of dragging the table wider&quot;
        src=&quot;/static/4704b31edd7770b426907655ea535aef/a6d36/dragscreen.png&quot;
        srcset=&quot;/static/4704b31edd7770b426907655ea535aef/222b7/dragscreen.png 163w,
/static/4704b31edd7770b426907655ea535aef/ff46a/dragscreen.png 325w,
/static/4704b31edd7770b426907655ea535aef/a6d36/dragscreen.png 650w,
/static/4704b31edd7770b426907655ea535aef/9d76a/dragscreen.png 829w&quot;
        sizes=&quot;(max-width: 650px) 100vw, 650px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I’ve recently seen another way of doing this via an enhancement which is slightly more complicated, but far more adaptive and robust. It’s described in the blog SM30, change standard width of Tablecontrol.&lt;/p&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;Use a Two-Step Dialog for Tables with 10+ fields.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If the table has more than 10 fields, you’ll be unable to avoid making your users scroll horizontally.  One way to make this easier is to use a two-step dialog.  When the users add a new entry, they will be taken to a separate screen where they can edit all the fields for one record.&lt;/p&gt;
&lt;ol start=&quot;6&quot;&gt;
&lt;li&gt;Disable Input for Read-only Fields WITHOUT Creating a Database View.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;One way to disable input is to mark the fields as “Read-Only” in the ABAP dictionary, but this is only possible for database views, not transparent tables.  If you are working with a transparent table and not a maintenance view, customizing this screen is easier than creating and maintaining a separate database view.  Open the screen for modification as in step 4.  Click the “Element List” tab and un-check the boxes in the Input column for those fields you do not want users to control (in case you will be filling them in automatically with custom code).  Examples of this are “Created By” and “Created On.” &lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 650px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/20d5acf1d3cbab344fa56eb001d9f5b7/57dc1/disableinput.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 88.34355828220859%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADvElEQVQ4yz2US3PjRBSF/edZsJoqFlAzC6qghkWgYJmCAJM4ju08/Ixi2Xq3nt16y5YlJ2wOt9uQxa2WZOn0d+657YEZVbieWxg9B/j5WsdPf21wtQgxWnt43CWIyx5RcVQVlx3CvH2//v95VLTv94OXqMWvEw8XtzYuFxxXy0jV5aOL0TbHzcrHZJtiamS4Wft4sErcbRLcahFGLzFGdP1gFbheMUx2KQYLk+OP+y2GKxf3eoyJxnC7dDBc2Bg/+7hdOerZmOpmZuKOyO/WLr1jqxouLAznskz6PsLAYAIXv1zim48X+O773/BlOAVzdDybAdyQw3V87CwfDq1by4PphtjaAZUPw41g+zGtAfw4RZA2GDDRQDcc3N5Nob3sINIMfhjBjVJkNfUqSeEGCQJRI8kqpNUBTpQhSs/3h/4NzeFE1UM0PQZuUsL1AzxrGg6HA9I0hbbZIkhy8GIPnpVqd4c3EHWPOKtpswxenCNMMrTHHrmfoCTShMIZeLzC1jAxHA5JjF70PEwfnuDQS6LcgwVkywvhJDVSIkjyRhFKQRYmaPtXlLRJXTTgdScJKzgswGq9RlXVyLIchuUQVaYEE5ErQpcIedW9EzISDOj54XhCtu9QUCXlURLWSmAynSLPyUYYYq1twKiHUjDmmSKRltPmpAhdSZcUCEmwO72h3J9Qt69EeDoTmjYJTiYoyhJd18HzQxhOAEE9lH0KqFxqzYbSlteWz5VgLAqk0kUmIDLqYV6ceygJZ/M5jiSWJInqm7QmQxEUCiOSSJTYGC6tBd1nCHmuUma+gfXTj5iNvoVpfCFBItyZNMRE2LZHWJZFIVn0QUGCDREKCiiGE6ZY0VgxIjRYrAQjunbcHVYPnzC++gq28fuZ0HI8LJZLZVf20HYZzVmlLIusUDYllU5DzWcrsNWGzjQ5SImemVjPPmMx/gjLvDkTSqLxeIK+72HZNjZbg/pRK0Ip6EVCpa7ZDOnkEf5SQ0C/x+SCsR2W90T459cwtkTIKOWdaeHx6QlRHCOOKVGP0engyrZPCfsRFYUw39BGmg5Pt+iYkQPqoekYeJ79gKfhB7j232dB03ah6zp2hoGqrrFvO2XRo9GRsyYt+1yeqHNYVpirWRRlC8PWoc0/Yy4tG9dnQS+UycY4dK/Yy0Gt9uf+0UhE1CeZcJDSCNEa0vEyRQeLtwiyFpxmVwgHnFuUekxzGJcomg4VDWZOa94c/1s79ecg15JOgZ8f1VmWf6ImpxJHeCRY7HsUhzf6/h812P8Cv/AYjCUta4oAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;disableinput&quot;
        title=&quot;disableinput&quot;
        src=&quot;/static/20d5acf1d3cbab344fa56eb001d9f5b7/a6d36/disableinput.png&quot;
        srcset=&quot;/static/20d5acf1d3cbab344fa56eb001d9f5b7/222b7/disableinput.png 163w,
/static/20d5acf1d3cbab344fa56eb001d9f5b7/ff46a/disableinput.png 325w,
/static/20d5acf1d3cbab344fa56eb001d9f5b7/a6d36/disableinput.png 650w,
/static/20d5acf1d3cbab344fa56eb001d9f5b7/57dc1/disableinput.png 718w&quot;
        sizes=&quot;(max-width: 650px) 100vw, 650px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;ol start=&quot;7&quot;&gt;
&lt;li&gt;Use Custom Logic When Appropriate.
A good database table needs validated, clean data.  If you cannot ensure this via check tables in the table definition, there are many points in the SAP standard dialog where you can add custom code to validate entries or do whatever else you need.  Enhancing a table maintenance dialog can get complicated, however, so the ins and outs will not be discussed here.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Some great resources for those who are interested:&lt;/p&gt;
&lt;p&gt;Table Maintenance Generator and its Modifications&lt;/p&gt;
&lt;p&gt;SAP Library – Extended Table Maintenance Events.&lt;/p&gt;
&lt;ol start=&quot;8&quot;&gt;
&lt;li&gt;Add a Custom Selection Screen for 50+ Records
If the custom table is large, its administrators may not want to see every entry on the overview screen.  They want to see if specific entries exist before adding new ones. This was a requirement by my business, and based on an SCN search for “filter sm30 selection screen,” I saw others had the same need.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It’s quite easy to restrict the display via SM30, but this is only after everything has been loaded.  The built-in selection criteria also gives only a small dialog box (not to mention you’re directly using SM30).&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 428px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/edded5bc4de333a11a93994df5a5b311/47730/no_sel_screen.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 82.20858895705521%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAAAsSAAALEgHS3X78AAACXElEQVQoz32TSW/TQBiG50ch9cyVI4vUKzduwM/gJ8AFbgghqCgQ1lalhLZpNjuOEy/jZTyOPV5ie7ynSVOmrYQiElV6ZmSN5tH3+psZkJbzop5DTH9zpMkRNh/2ya+ee9hnkHUOurYTZLSoo7QCg5GCsP3s+d6dR2/uPn53/+nOvSfvbz98vbX9amv75Tq3Hrw4aKn1fDGlJbAm3sQNum2hzUktbvynLRx3xWaLH0iGijzFJKtA5A0ETUNuXs6SrARHA63J653eGFl4rECGpGrCSNJMq6jPytl8lepsEU1pT3ZEOxUxBadD1BqiE06RocEN5YEom7aH3RBN/DApWLZV4rRygqSvuKqbK04GIPZNNxIkU4a6KMGRoiV5nZZntJjFWfUfNK/dkKpW4NMZiSsgIwJxIMiIVRbGiqQaYZLHeb1u/pMV5JOkdqMKGG6kWv5QsVQDdTiBFyUSJsmNsmQQJy7tsAA+XQTpQjEINCxelEUZOn60MfO1TEJqTOIwOw+zBYgDLnBP+UFH1TGr3BdG2PGZHKXlBrmonSDl+weR10XaMUj8Qx9/5/kT24skaCg6ujk2k3udT8HkJxx/BlG+ZGhWwARWkLHRnNJsyhqZFq4fY5LS6oKWSxBnZZQWqumwnOxfL2EfK0wvV+qsWmbVeT67YCdkYELzKqI5kyu2AyJC2dluIq+XYRy2Ojv7zd2To/1R64dhB1cPowRssJycCNvcqDuQ1ukLymm31/j2drex0/jyce/rB3a30/KyoyC+kh1vKkFT1tBGFB3rlm9gT8cEWl4QZ9d9+Qtz+0riNmAW8wAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;no sel screen&quot;
        title=&quot;no sel screen&quot;
        src=&quot;/static/edded5bc4de333a11a93994df5a5b311/47730/no_sel_screen.png&quot;
        srcset=&quot;/static/edded5bc4de333a11a93994df5a5b311/222b7/no_sel_screen.png 163w,
/static/edded5bc4de333a11a93994df5a5b311/ff46a/no_sel_screen.png 325w,
/static/edded5bc4de333a11a93994df5a5b311/47730/no_sel_screen.png 428w&quot;
        sizes=&quot;(max-width: 428px) 100vw, 428px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This is no selection screen for end users!&lt;/p&gt;
&lt;p&gt;Instead, it’s better to create a custom report with select-options that calls the function module “VIEW&lt;em&gt;MAINTENANCE&lt;/em&gt;CALL” I mentioned above. The FM requires all the select-options to be in one parameter.  Here are the highlights of the code needed for that.&lt;/p&gt;
&lt;p&gt;Add a Selection Screen to a Table Maintenance Dialog&lt;/p&gt;
&lt;ol start=&quot;9&quot;&gt;
&lt;li&gt;Integrate Your TMD Into a View Cluster or Config Table
Once the INNER workings of a table maintenance dialog are optimized for user pleasure, give it context in the OUTSIDE environment.  Add it to a view cluster so multiple related tables can be maintained at once, or add it to the IMG config settings if appropriate.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These activities are detailed in two entries from my favorite series on SCN (so far):&lt;/p&gt;
&lt;p&gt;Getting the basics right – Creating the perfect config table (Part 2, View Clusters)&lt;/p&gt;
&lt;p&gt;Getting the basics right – Creating the perfect config table (Part 4, IMG integration)&lt;/p&gt;
&lt;p&gt;Good UI Goes a Long Way&lt;/p&gt;
&lt;p&gt;If this is done well, users will be happy, or at least not angry, and that’s what we developers all hope for.  Less time will be spent responding to users’ little requests in the future, and you will be far better off for it.&lt;/p&gt;
&lt;p&gt;So, what other ways have you been able to improve upon the standard TMD?&lt;/p&gt;</content:encoded></item><item><title><![CDATA[A Dream for SE80: Github Integration]]></title><description><![CDATA[Originally posted at https://blogs.sap.com/2013/09/18/a-dream-for-se80-github-integration/ When I heard Code Exchange was closing, I was…]]></description><link>https://www.ericp.co/posts/a-dream-for-se80-github-integration</link><guid isPermaLink="false">https://www.ericp.co/posts/a-dream-for-se80-github-integration</guid><pubDate>Wed, 18 Sep 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Originally posted at &lt;a href=&quot;https://blogs.sap.com/2013/09/18/a-dream-for-se80-github-integration/&quot;&gt;https://blogs.sap.com/2013/09/18/a-dream-for-se80-github-integration/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When I heard Code Exchange was closing, I was bummed.  I read that a new code exchange 2.0 is being developed, but as I write this it is still under construction.  As many people have pointed out, however, that doesn’t need to stop SAP developers from sharing code with one another.&lt;/p&gt;
&lt;p&gt;For us ABAPers, we have few choices on how to share code, and it’s not easy to share non-code development objects.  For simple programs, I can copy and paste from any forum, but what about a program has a dozen custom data elements and a few custom global classes?  Well, thanks to the fantastic SAPLink project (with which I am not affiliated), that has become a lot easier.  It’s as easy as downloading a .nugg file and importing it, or so I hear.&lt;/p&gt;
&lt;p&gt;I want to take the idea behind SAPLink one step further.  Instead of searching the web via browser (and by the web, I mean Google Code and Github) for a .nugg file, downloading it to a file directory, and importing it via SAPGUI, can’t we do this all from SAPGUI?  We’re trying to share code, so why not share while using the place where we work on the code, i.e. SE80?  If you’re thinking, “That’s not where I work on the code!  I use Eclipse!” well, good for you.  I hope to join your smug ranks soon, but most of what I’m proposing is probably applicable to Eclipse development too.  Certainly an ABAP-based github client is reusable.&lt;/p&gt;
&lt;p&gt;So rather than spending 5 minutes explaining it, I spent half an hour stumbling through MS Paint, drawing what I had in mind.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 552px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b125e01836cc495473cee11dcb321f9e/08c0b/github_mockup_scn.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 101.840490797546%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAD60lEQVQ4y42U21PbRhSH/R/3tdO+5aHTZqaXmSYzaZuEpklIU0jKJQOEECA4BGPAtix8k2zZsmXJknUzNgYT0q/HpqWkzbR9+GZ3dle/PTp7zi/RtEOsTkTVdGk6IbYXCz1aMvejAbWmR8MK8OMhppxttMfzY1nzcYM+TTsg6A3pDUYcDc9J9AZ9DLvO6cmI0WjE6ekpZ2dn9PvHRFGMY0doTYN6LYdT0QjCI6xWF1cuDoIjPC8ijo7xuj75Yo5EN+qTKWgSoYNWtyQiB73RxnQCzE5IvR1StTwqRhNDzjScCN3syn5MsxPLGcHpUbd9yoZBouHG3Hm6zq3HyzKuceP+IjcezPP0lcLLfJP1vMlGvsXGocW62uKlYk7W13Lm+yjjs20SloS8lbdIlRwWNhWmFw5Zea3wfLfG6m5V1m12ihekhH3N5kB3PoA9IaEeFnj66Ft2Nu+SXLvD3vY9dPUJmjo7oZyboSRo+VmyqWkKmo7XH2GHfZxw8A8Sqprj2f2PyL74hNzap+wufYyxew03/xkdISx+QSDE5es0Dz6nXNUJj9/ixgM8ed2/k1DyeeZmvkZJTQk/Ujy4TyX3UHiAcfiIsDVPYM4RW/M0yzOU9SqBROhK6bgiMBmvkFCUPKtzN0RoCjV9F6PwkI4xI0K/Egi+0G3PE3YWMKsi2GgQjMCVGvX+EL06JnI5hcXHX5LdmWIveZu9rds0tVm61iJeYw5fn8XP/ESYvoe5egtt4xVBpY736g1eOod7dDLhT9FENpvhyfQ1ygc/kEneJJ/+nrYyRbD0lQhN4W/dJFi4Ti/1Ha2Vb9Beb0sKHNyqKRe28XYzeFLglxGqhRIvnv9CrbyCmpmnrq/imeu42gpdewvPSdJJPsZ//TONZamA5VWCrRTe5jZerog3nnfjyygTDbPFYUlHM1qTngykZ0PZbEt9NqRPu4NzXH9ANxzSqrWp7+XwpWRcEZkIjR/mSh4TRqNJVlGpSH0FYUT/eMhA6A+G1OQBcuqBtKVBfHKO6froVgf/+OxCaJy/q48yFqwaNaq1PK6r43SqlCtZisUdiqUUB/vL7KfX2Ejuk1bLEnFXxNv4/dNJiXhXuMyhXjVYWV0iuZ3kTXpPOkGjUClTlPGwVEBRVZZfbPLs+Ut29hW0hoU/uKjDDxZ23bQo6XUyikSRKVCsWhPPq4oPerF8GJ2I+9jiRDZqqXYR4b8JjnNoS9K9SEy1E0xsqyW2ZYhledEQ/2hEJK0mzUHHPxJ7s//65Q8LtrDEwnonEA/fXdI7+U2Ezun2TulORN/Jy8f/U1AsP5aPg/7Ze4SDtxPBcZTjS9py7r8Efwdgl55RWotO2wAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Screenshot of desired functionality&quot;
        title=&quot;Screenshot of desired functionality&quot;
        src=&quot;/static/b125e01836cc495473cee11dcb321f9e/08c0b/github_mockup_scn.png&quot;
        srcset=&quot;/static/b125e01836cc495473cee11dcb321f9e/222b7/github_mockup_scn.png 163w,
/static/b125e01836cc495473cee11dcb321f9e/ff46a/github_mockup_scn.png 325w,
/static/b125e01836cc495473cee11dcb321f9e/08c0b/github_mockup_scn.png 552w&quot;
        sizes=&quot;(max-width: 552px) 100vw, 552px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Seriously, how cool would this be?&lt;/p&gt;
&lt;p&gt;From what I can tell, although it’s not possible to add tools to SE80 like this, it would still be very helpful to copy the general UI into another transaction.  It could have two or three pushbuttons on the left like SE80, but they would be along the lines of Github Repositories, Search Github, and Package Browser.  From github repositories, you could view your own repos.  Search Github would return a results list of repos, from which you could view the contents, readme, and import as an SAP development package.  Package Browser would allow a user to select and push his or her development packages to github.&lt;/p&gt;
&lt;p&gt;Right now I’m thinking a 1-to-1 ratio of packages to repositories would work best for code management and sharing.  If I download/clone a repository, it becomes a package, and if I push a package to github, it becomes a repository, and any subpackages do not – they are just part of the .nugg file.&lt;/p&gt;
&lt;p&gt;There are a few problems that need answers if this will get developed, such as how to handle the github readme files, but boy howdy, this would be a dream come true.&lt;/p&gt;
&lt;p&gt;If this were developed, would you use it?  What other features would you like to see?&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Add a Selection Screen to a Table Maintenance Dialog]]></title><description><![CDATA[Originally posted at https://blogs.sap.com/2013/08/22/add-a-selection-screen-to-a-table-maintenance-dialog/. When end users will maintain a…]]></description><link>https://www.ericp.co/posts/add-a-selection-screen-to-a-table-maintenance-dialog</link><guid isPermaLink="false">https://www.ericp.co/posts/add-a-selection-screen-to-a-table-maintenance-dialog</guid><pubDate>Thu, 22 Aug 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Originally posted at &lt;a href=&quot;https://blogs.sap.com/2013/08/22/add-a-selection-screen-to-a-table-maintenance-dialog/&quot;&gt;https://blogs.sap.com/2013/08/22/add-a-selection-screen-to-a-table-maintenance-dialog/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When end users will maintain a z-table with 100+ rows, it helps to be able to restrict the selection by any number of selection criteria.  This document attempts to define a “best practice” method for calling a table maintenance dialog from a selection screen.&lt;/p&gt;
&lt;p&gt;Current Table Maintenance&lt;/p&gt;
&lt;p&gt;The standard way to show a table maintenance dialog is via SM30, Call View Maintenance –&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 553px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5e5f09ed891f9b147a6e3aba9bfd6259/74cfa/sm30.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 65.03067484662577%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAB3klEQVQoz3XQW2/aMBQA4Pz/P7GLtr2sqOqk0YkW2jJYRqtCR0cuJLFjBzuxkzhXSBBMmhO2PVSZ9Mk659jHOrYynpuvzvrvL657g+nrs/7Hy/G7i2Hv6tub3uWHT6O354Pz4ezB4jODzkz/BeXLdNkbLfqq0Vf1z63bH3C8dG+fgAykuyWarDadFMP1fwLfwKHmMgNzHXHI0r8yuYIgAX43Jd0dkt1RlPu4qKWoqHm2+yfM/6eSFIB9zUYeEzJhScmTPM3LkyjJQ9nf5XS1AkioAeKQyA0EYikRhZ9sT6goN3E3lm6b5nsNXd3r1w/6QF3JD1zi9MlNpIUrFs3aYQ6F7JfDKxYOZ8/OZG5MFqZFM4dt7aCUHFYCvu1ks5KKrRxecUg8edQeDfQMueHFTBTtywsS5U5QANbc8oIVFH+acVStaQHDyo32kFdeXG9ETZI9iioU72FYy3qrCWR6KvpJ+2HUh1HkIKxT3wwCm/prQk0HrgJuQ2fFmIU93dsYhK4x1uQZ6K4IMXma86xSNt5CsO+2eUO9KcVqsFEDb2qbI+7P9OWQE9V17hAYYzgF1g1BE7mFwFeeCJ7VSlweguwQlUeeS4fWMSyPrCn+YvkhLI680QYyLds0q+TYvwHhJrOQInweOAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;SM30 screenshot&quot;
        title=&quot;SM30 screenshot&quot;
        src=&quot;/static/5e5f09ed891f9b147a6e3aba9bfd6259/74cfa/sm30.png&quot;
        srcset=&quot;/static/5e5f09ed891f9b147a6e3aba9bfd6259/222b7/sm30.png 163w,
/static/5e5f09ed891f9b147a6e3aba9bfd6259/ff46a/sm30.png 325w,
/static/5e5f09ed891f9b147a6e3aba9bfd6259/74cfa/sm30.png 553w&quot;
        sizes=&quot;(max-width: 553px) 100vw, 553px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;– or a custom parameter transaction that calls SM30 for a specific table, with parameters VIEWNAME and UPDATE = ‘X’.&lt;/p&gt;
&lt;p&gt;Neither of these provide an initial selection screen.  Entries can be restricted by checking the “Enter conditions” radiobutton, but users are more familiar with selection screens than with the dialog box that pops up.  Therefore it is good UI to use a selection screen instead of the “Enter conditions” radiobutton.&lt;/p&gt;
&lt;p&gt;Example Selection Screen Definition&lt;/p&gt;
&lt;p&gt;In this example, an executable report has been created with selection screen.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;abap&quot;&gt;&lt;pre class=&quot;language-abap&quot;&gt;&lt;code class=&quot;language-abap&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;REPORT&lt;/span&gt;  z_maintain_mytable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;DATA&lt;/span&gt; mytable    &lt;span class=&quot;token keyword&quot;&gt;TYPE&lt;/span&gt; z_mytable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;DATA&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;selections&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TYPE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TABLE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;OF&lt;/span&gt; vimsellist&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;DATA&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;selection&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;TYPE&lt;/span&gt; vimsellist&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;SELECT-OPTIONS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; so_selop1 &lt;span class=&quot;token keyword&quot;&gt;FOR&lt;/span&gt; mytable–myfield1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                 so_selop2 &lt;span class=&quot;token keyword&quot;&gt;FOR&lt;/span&gt; mytable–myfield2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;PARAMETERS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; p_param1 &lt;span class=&quot;token keyword&quot;&gt;TYPE&lt;/span&gt; z_mytable–myfield3&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            p_param2 &lt;span class=&quot;token keyword&quot;&gt;TYPE&lt;/span&gt; z_mytable–myfield4&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 647px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6ad196ab058513986d097e4e3d91a74b/ca12d/sel_screen.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 46.012269938650306%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABPklEQVQoz6WQTU/CMBjH+/2/hSZ60RijF0MMxMTgCwcTLjIWBWTtunUv7dpNpoc/XWGA4MHEwy/P255fn4yMZhGOL29xet3F2c29jT2cd/o4ueri6KKDu+EUD6MQ/Vf6C2zNtibejKH34mEwZngaBRa6JnA8277DW8VBW7c9j2Lgx7bPXU5olMKfR+B5CZoWYKneQBMFJjIEie1nBnMh8UYFeCLBmlmmwWUN33/ELBgjlAsQFiUY2ytjVYI3H+QtBmGqkEuFVBlkRQmRF/gIBRKpIaRxO4n+xnQyBOMTCP0FwpMc70GMqBFkhUVvaK5Q2qCwOKmuIKwkUtUKWTriorbyhcuJNJ9u2Q2t9ABp3Kz5JbwVrKPLd8U2J6qqbVG54q+0y7v1Vlgu3Mu7g+jHBStc3Qj2ZPtYYX3w4n9YAuKFnLaX5unBAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Selection screen screenshot&quot;
        title=&quot;Selection screen screenshot&quot;
        src=&quot;/static/6ad196ab058513986d097e4e3d91a74b/ca12d/sel_screen.png&quot;
        srcset=&quot;/static/6ad196ab058513986d097e4e3d91a74b/222b7/sel_screen.png 163w,
/static/6ad196ab058513986d097e4e3d91a74b/ff46a/sel_screen.png 325w,
/static/6ad196ab058513986d097e4e3d91a74b/ca12d/sel_screen.png 647w&quot;
        sizes=&quot;(max-width: 647px) 100vw, 647px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Calling Function Modules&lt;/p&gt;
&lt;p&gt;When the user clicks execute, the program needs to read their selections and call the table maintenance dialog.  The following code shows how this is easily done by using function modules ‘VIEW&lt;em&gt;RANGETAB&lt;/em&gt;TO&lt;em&gt;SELLIST’ and ‘VIEW&lt;/em&gt;MAINTENANCE_CALL’.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;abap&quot;&gt;&lt;pre class=&quot;language-abap&quot;&gt;&lt;code class=&quot;language-abap&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;START-OF-SELECTION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;DEFINE&lt;/span&gt; addsel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;CALL&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;FUNCTION&lt;/span&gt; ‘VIEW_RANGETAB_TO_SELLIST’
      &lt;span class=&quot;token keyword&quot;&gt;EXPORTING&lt;/span&gt;
        fieldname          &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &amp;amp;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
        append_conjunction &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘AND’
      &lt;span class=&quot;token keyword&quot;&gt;TABLES&lt;/span&gt;
        sellist            &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;selections&lt;/span&gt;
        rangetab           &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &amp;amp;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;[]&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;END-OF-DEFINITION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;DEFINE&lt;/span&gt; addparam&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;IF&lt;/span&gt; &amp;amp;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;IS&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;INITIAL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;CLEAR&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;selection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;selection&lt;/span&gt;–viewfield &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &amp;amp;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;selection&lt;/span&gt;–value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &amp;amp;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;selection&lt;/span&gt;–and_or &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘AND’&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;selection&lt;/span&gt;–operator &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘EQ’&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;APPEND&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;selection&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TO&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;selections&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;ENDIF&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;END-OF-DEFINITION&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

  add_sel ‘MYFIELD1’ so_selop1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
  add_sel ‘MYFIELD2’ so_selop2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
  add_par ‘MYFIELD3′ p_param1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
  add_par ‘MYFIELD4′ p_param2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;CALL&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;FUNCTION&lt;/span&gt; ‘VIEW_MAINTENANCE_CALL’
    &lt;span class=&quot;token keyword&quot;&gt;EXPORTING&lt;/span&gt;
      action                &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘U’ “for &lt;span class=&quot;token keyword&quot;&gt;Update&lt;/span&gt;
      view_name             &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘Z_MYTABLE’
      complex_selconds_used &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘X’
    &lt;span class=&quot;token keyword&quot;&gt;TABLES&lt;/span&gt;
      dba_sellist           &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;selections&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;EXCEPTIONS&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;OTHERS&lt;/span&gt;                &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;IF&lt;/span&gt; sy–subrc &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;MESSAGE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;ID&lt;/span&gt; sy–msgid &lt;span class=&quot;token keyword&quot;&gt;TYPE&lt;/span&gt; sy–msgty &lt;span class=&quot;token keyword&quot;&gt;NUMBER&lt;/span&gt; sy–msgno
               &lt;span class=&quot;token keyword&quot;&gt;WITH&lt;/span&gt; sy–msgv1 sy–msgv2 sy–msgv3 sy–msgv4&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;ENDIF&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Horray!  That is all. In only 46 lines (plus two for every select-option or parameter), this will bring the user to from the selection-screen to the table maintenance screen.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 463px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5cd423dd088e8e2e6e3ec3705f929e37/71ce0/tab_maint.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 125.76687116564416%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAZCAYAAAAxFw7TAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACZElEQVQ4y82Va1PaUBCG8///QT+obaeUKfWCyr0ZkKAElBCBcJH7JRDIBcJF7PTL282BdnS0RYvO9MMzu2zO2bzL7jnhlJaO3f0wdj0BfPTy+HAYhtsvkOWx8zVEz0LY8QThCYks9s7lxR6tf38Qxs4XP/YOIsx3ncbJRsDJNRXuUBKfgiIOo1l44zkcJxScCFdwnURwxGfhCpzhc/Ab3GGB1kgIpStEGceCjECqhCD5octVjKt1NQiZAuK5BqQbFWKhhXSpC6lch5CWkJLruMgVEbu6QOwyg0y5g3LPhNLWUeqaKHb0NQZKFOdyDQ3HcRknZxJ853lSJuMomsFpIk9qrxEQFfjIP00UaN014oXuPToQyMbyJKA2wHCyAFdp9sGfZ+DjE4iKMkS5jGhShp9+B6NJBKIikhS7Umq4LNQglVrIlldIpSZyVRWxdBp8SoK1+AGuWG2h2h5A1ScrDBu90RgdzfxtB+YUmjVjOP4DKNbXDTR6pNC+BafctNBQdRiz7yT5FoPxHNp4gdF0iZG9ZNaJ/wmNyjSmd6uXOiUrpLDeG7HNGiVjb3TUUNIHTB7j/GeOAGu2hGnPmc8UOgn16ZJtHFhzxnC9YRO/EhpvnFDfMuHd8xRqG3haYXXV5X9V6Oyx5vcUFkhhret0+ZYl6pszhsbGZzN96wmFbGweKJxtLPevJdfVbZqyeKop+v82Nm8/2KPXHuxtm7J83ZMypsE27cXjk8IWvPSksPuQ7kXTZoK4fKWJamfIHjonRDWmDGe4n0N/bdt0s7NvSp+u/ZZmoafb6JL/clb7evTpcKr8CayOLe/jFAtnAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Table maintenance dialog screenshot&quot;
        title=&quot;Table maintenance dialog screenshot&quot;
        src=&quot;/static/5cd423dd088e8e2e6e3ec3705f929e37/71ce0/tab_maint.png&quot;
        srcset=&quot;/static/5cd423dd088e8e2e6e3ec3705f929e37/222b7/tab_maint.png 163w,
/static/5cd423dd088e8e2e6e3ec3705f929e37/ff46a/tab_maint.png 325w,
/static/5cd423dd088e8e2e6e3ec3705f929e37/71ce0/tab_maint.png 463w&quot;
        sizes=&quot;(max-width: 463px) 100vw, 463px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This is a collaborative document.  If there are better ways of achieving this functionality don’t hesitate to chime in and contribute!&lt;/p&gt;</content:encoded></item></channel></rss>