def write_url_external(row1, col1, row2, col2, url, str = nil, format = nil)       #:nodoc:
    # Network drives are different. We will handle them separately
    # MS/Novell network drives and shares start with \\
    if url =~ /^external:(\\\\|\/\/)/
      return write_url_external_net(row1, col1, row2, col2, url, str, format)
    end

    record      = 0x01B8                       # Record identifier
    length      = 0x00000                      # Bytes to follow

    xf     = format || url_format        # The cell format

    # Strip URL type and change Unix dir separator to Dos style (if needed)
    #
    url = url.sub(/^external:/, '').gsub(%r|/|, '\\')

    # Write the visible label but protect against url recursion in write().
    str = url.sub(/\#/, ' - ') unless str
    error        = write_string(row1, col1, str, xf)
    return error if error == -2

    # Determine if the link is relative or absolute:
    # Absolute if link starts with DOS drive specifier like C:
    # Otherwise default to 0x00 for relative link.
    #
    absolute    = 0x00
    absolute    = 0x02  if url =~ /^[A-Za-z]:/

    dir_long, link_type, sheet_len, sheet = analyze_link(url, absolute)

    # Pack the link type
    link_type      = [link_type].pack("V")

    # Calculate the up-level dir count e.g. (..\..\..\ == 3)
    up_count    = 0
    while dir_long.sub!(/^\.\.\\/, '')
      up_count += 1
    end
    up_count    = [up_count].pack("v")

    # Store the short dos dir name (null terminated)
    dir_short   = dir_long + "\0"

    # Store the long dir name as a wchar string (non-null terminated)
    dir_long = dir_long.split('').join("\0") + "\0"

    # Pack the lengths of the dir strings
    dir_short_len = [dir_short.bytesize].pack("V")
    dir_long_len  = [dir_long.bytesize].pack("V")
    stream_len    = [dir_long.bytesize + 0x06].pack("V")

    # Pack the undocumented parts of the hyperlink stream
    unknown1 = ['D0C9EA79F9BACE118C8200AA004BA90B02000000'].pack("H*")
    unknown2 = ['0303000000000000C000000000000046'].pack("H*")
    unknown3 = ['FFFFADDE000000000000000000000000000000000000000'].pack("H*")
    unknown4 = [0x03].pack("v")

    # Pack the main data stream
    data        = [row1, row2, col1, col2].pack("vvvv") +
    unknown1     +
    link_type    +
    unknown2     +
    up_count     +
    dir_short_len+
    dir_short    +
    unknown3     +
    stream_len   +
    dir_long_len +
    unknown4     +
    dir_long     +
    sheet_len    +
    sheet

    # Pack the header data
    length      = data.bytesize
    header      = [record, length].pack("vv")

    # Write the packed data
    append(header, data)

    error
  end
def write_url_external(row1, col1, row2, col2, url, str = nil, format = nil)       #:nodoc:
    # Network drives are different. We will handle them separately
    # MS/Novell network drives and shares start with \\
    if url =~ /^external:(\\\\|\/\/)/
      return write_url_external_net(row1, col1, row2, col2, url, str, format)
    end

    record      = 0x01B8                       # Record identifier
    length      = 0x00000                      # Bytes to follow

    xf     = format || url_format        # The cell format

    # Strip URL type and change Unix dir separator to Dos style (if needed)
    #
    url = url.sub(/^external:/, '').gsub(%r|/|, '\\')

    # Write the visible label but protect against url recursion in write().
    str = url.sub(/\#/, ' - ') unless str
    error        = write_string(row1, col1, str, xf)
    return error if error == -2

    # Determine if the link is relative or absolute:
    # Absolute if link starts with DOS drive specifier like C:
    # Otherwise default to 0x00 for relative link.
    #
    absolute    = 0x00
    absolute    = 0x02  if url =~ /^[A-Za-z]:/

    dir_long, link_type, sheet_len, sheet = analyze_link(url, absolute)

    # Pack the link type
    link_type      = [link_type].pack("V")

    # Calculate the up-level dir count e.g. (..\..\..\ == 3)
    up_count    = 0
    while dir_long.sub!(/^\.\.\\/, '')
      up_count += 1
    end
    up_count    = [up_count].pack("v")

    # Store the short dos dir name (null terminated)
    dir_short   = dir_long + "\0"

    # Store the long dir name as a wchar string (non-null terminated)
    dir_long = dir_long.split('').join("\0") + "\0"

    # Pack the lengths of the dir strings
    dir_short_len = [dir_short.bytesize].pack("V")
    dir_long_len  = [dir_long.bytesize].pack("V")
    stream_len    = [dir_long.bytesize + 0x06].pack("V")

    # Pack the undocumented parts of the hyperlink stream
    unknown1 = ['D0C9EA79F9BACE118C8200AA004BA90B02000000'].pack("H*")
    unknown2 = ['0303000000000000C000000000000046'].pack("H*")
    unknown3 = ['FFFFADDE000000000000000000000000000000000000000'].pack("H*")
    unknown4 = [0x03].pack("v")

    # Pack the main data stream
    data        = [row1, row2, col1, col2].pack("vvvv") +
    unknown1     +
    link_type    +
    unknown2     +
    up_count     +
    dir_short_len+
    dir_short    +
    unknown3     +
    stream_len   +
    dir_long_len +
    unknown4     +
    dir_long     +
    sheet_len    +
    sheet

    # Pack the header data
    length      = data.bytesize
    header      = [record, length].pack("vv")

    # Write the packed data
    append(header, data)

    error
  end
Write links to external directory names such as 'c:\foo.xls',
 c:\foo.xls#Sheet1!A1', '../../foo.xls'. and '../../foo.xls#Sheet1!A1'.

 Note: Excel writes some relative links with the $dir_long string. We ignore
 these cases for the sake of simpler code.

 See also write_url() above for a general description and return values.