Pretty printing of the numpy ndarrays
If A.ndim is not in 1, 2, 3, your code tries to return a non-existing string s. It would be better to be explicit about what your code supports atm:

def ndtotext(A, w=None, h=None):
    ...
    else:
        raise NotImplementedError("Currently only 1 - 3 dimensions are supported")
    return s


While we are at the point of having your code be clear about what is happening, you should add a docstring explaining what your code does:

def ndtotext(A, w=None, h=None):
    """Returns a string to pretty print the numpy.ndarray `A`.

    Currently supports 1 - 3 dimensions only.
    Raises a NotImplementedError if an array with more dimensions is passed.

    Describe `w` and `h`.
    """
    ...


Next, Python has an official style-guide, PEP8, which programmers are encouraged to follow. One of the things it recommends is surrounding operators with spaces (which I fixed in the rest of the code) and using lower_case for variables and functions (which I left as is for now).

Now, let's come to your actual code:


You calculate some values multiple times (like str(A[0])), save those to a variable.
If you want to compare to None, use is (since it is a singleton).
No else needed after an if...return (this is a matter of personal style, I prefer not having the additional level of indentation).
Use str.rjust to add enough whitespace in front of your strings. You could also use str.format for this, but it looks less nice. 
Your w has a weird structure, with the width of the first column being the last entry and the rest starting at zero.
Give the unicode values names. And then add functions to draw a line of specified length.
String addition is costly and slow. Try to consistently use building a list and str.joining it.

UPPER_LEFT = u'\u250c'
UPPER_RIGHT = u'\u2510'
LOWER_LEFT = u'\u2514'
LOWER_RIGHT = u'\u2518'
HORIZONTAL = u'\u2500'
VERTICAL = u'\u2502'

def upper_line(width):
    return UPPER_LEFT + HORIZONTAL * width + UPPER_RIGHT

def lower_line(width):
    return LOWER_LEFT + HORIZONTAL * width + LOWER_RIGHT

def left_line(height):
    return "\n".join([UPPER_LEFT] + [VERTICAL] * height + [LOWER_LEFT])

def right_line(height):
    return "\n".join([UPPER_RIGHT] + [VERTICAL] * height + [LOWER_RIGHT])

def ndtotext(A, w=None, h=None):
    """Returns a string to pretty print the numpy.ndarray `A`.

    Currently supports 1 - 3 dimensions only.
    Raises a NotImplementedError if an array with more dimensions is passed.

    Describe `w` and `h`.
    """
    if A.ndim == 1:
        if w is None:
            return str(A)
        s = " ".join([str(value).rjust(width) for value, width in zip(A, w)])
        return '[{}]'.format(s)
    elif A.ndim == 2:
        widths = [max([len(str(s)) for s in A[:, i]]) for i in range(A.shape[1])]
        s = "".join([' ' + ndtotext(AA, w=widths) + ' \n' for AA in A])
        w0 = sum(widths) + len(widths) - 1 + 2 # spaces between elements and corners
        return upper_line(w0) + '\n'  + s + lower_line(w0)
    elif A.ndim == 3:
        h = A.shape[1]
        strings = [left_line(h)]
        strings.extend(ndtotext(a) + '\n' for a in A)
        strings.append(right_line(h))
        return '\n'.join(''.join(pair) for pair in zip(*map(str.splitlines, strings)))
    raise NotImplementedError("Currently only 1 - 3 dimensions are supported")



This can probably be even more compactified, but I think it is a good start.

Example usage:

x = np.arange(12)

print(ndtotext(x))
[ 0  1  2  3  4  5  6  7  8  9 10 11]

print(ndtotext(x.reshape(3, 4)))
┌───────────┐
 [0 1  2  3] 
 [4 5  6  7] 
 [8 9 10 11] 
└───────────┘

print(ndtotext(x.reshape(3, 2, 2)))
┌┌─────┐┌─────┐┌───────┐┐
│ [0 1]  [4 5]  [ 8  9] │
│ [2 3]  [6 7]  [10 11] │
└└─────┘└─────┘└───────┘┘