Achieving Super or Subscript graticule labels in QGIS Composer windows?

Unicode has some superscript and subscript characters in it as described on Wikipedia

Here are two custom functions that can be entered in the QGIS Python Function Editor that superscript or subscript the digits in strings passed to them:

Superscript

@qgsfunction(args='auto', group='Custom')
def supscr_num(inputText, feature, parent):
  """ Converts any digits in the input text into their Unicode superscript equivalent.
Expects a single string argument, returns a string"""
  supScr = (u'\u2070',u'\u00B9',u'\u00B2',u'\u00B3',u'\u2074',u'\u2075',u'\u2076',u'\u2077',u'\u2078',u'\u2079')
  outputText = ''

  for char in inputText:
    charPos = ord(char) - 48
    if charPos <0 or charPos > 9:
        outputText += char
    else:
        outputText += supScr[charPos]
  return outputText

Subscript

@qgsfunction(args='auto', group='Custom')
def subscr_num(inputText, feature, parent):
""" Converts any digits in the input text into their Unicode subscript equivalent.
Expects a single string argument, returns a string"""
  outputText = ''

  for char in inputText:
    charPos = ord(char) - 48
    if charPos <0 or charPos > 9:
        outputText += char
    else:
        outputText += unichr(charPos + 8320)
  return outputText

These can then be used in an expression as follows:

supscr_num('4') || "123" || supscr_num('000')

Returning the ⁴123⁰⁰⁰ in the question

A more generic example of the same expression:

supscr_num(to_string(@grid_number // 100000)) || lpad ( to_string ( (@grid_number % 100000) // 1000),3,'0') || supscr_num(lpad (to_string(@grid_number % 1000),3,'0'))

Unfortunately there is incomplete support for the latin alphabet super and subscripts in unicode, so this technique cannot be extended completely.

EDIT - Note on fonts

Note that the unicode characters generated by the tool aren't present in every font. For example, using the following label expression:

 '1234567890'  || '\n'  ||  subscr_num(  '1234567890') ||  '\n'  || supscr_num(  '1234567890') 

Generates the following using Arial:

Arial exmaple

But using Times New Roman all the digits are present:

Times New Roman example


If you have grid coordinates and want the first two figures to be large and the rest to be superscripts you can do it without python functions.

The trick is to use string processing to split the number into parts, and then replace the numbers with superscript numbers with the replace function.

concat(left(@grid_number,2),
       replace( substr(@grid_number,3,99) ,
                array('1','2','3','4','5','6','7','8','9','0'),
                array('¹','²','³','⁴','⁵','⁶','⁷','⁸','⁹','⁰')
              )
       )

Put that as a custom format grid label with the expression button. Similar techniques can be used to have other parts of the label as superscripts or even subscripts.

Anything more complex than this I would do as a Python function.