Spreadsheet PasteHtml - Line breaks not working

So we are using the PasteHtml executeMethod to paste html in the editor with a loop script.
For example:

This is a test
This should be a new line

If we do this we get the following:


As you can see the text is spread over 2 cells because of the

After long time of trial and error I found if we transform the
to unicode \u2028 the line break is set as it should

This is a test\u2028 This should be a new line



But as you can see in the formula the line break isn’t taken over. And thus if we download the file, it’s not on a separate line:

This is really annoying as the customer loses his structure.
Am I doing something wrong or?

Kind regards,
Laurens (Sequesto)

Hello @LaurensSequesto,
Please provide the full script you are using, the original document, and a screen recording of the steps to reproduce the issue.
Also, what version of Document Server are you using?

Hi Dmitrii,

We are using the spreadsheet editor version 8.2.2.22.

This is the code responsible for converting our value from the richt text editor we use to html for pasting with pasteHtml.

// export const LINE_BREAK = '
' 
// export const LINE_BREAK = '\u2028' 
export const LINE_BREAK = '<br>'

const convertTipTapToOnlyOfficeHtml = (tiptapHtml: string): string => {
  if (!tiptapHtml) return ''

  // Create a DOM parser to parse the HTML string
  const parser = new DOMParser()
  const doc = parser.parseFromString(tiptapHtml, 'text/html')

  // Process the document
  const processedHtml = processNode(doc.body)

  return processedHtml
}

const processNode = (node: Node): string => {
  let result = ''

  // Process each child node
  node.childNodes.forEach((child) => {
    if (child.nodeType === Node.TEXT_NODE) {
      // Text node - add its content
      result += child.textContent
    } else if (child.nodeType === Node.ELEMENT_NODE) {
      const element = child as HTMLElement
      const tagName = element.tagName.toLowerCase()

      if (tagName === 'ul') {
        // Process unordered list
        element.querySelectorAll('li').forEach((li) => {
          result += `• ${li.textContent}${LINE_BREAK}`
        })
      } else if (tagName === 'ol') {
        // Process ordered list
        element.querySelectorAll('li').forEach((li, index) => {
          result += `${index + 1}. ${li.textContent}${LINE_BREAK}`
        })
      } else if (tagName === 'p') {
        // Process paragraph - extract content without the p tags
        if (element.textContent?.trim()) {
          // Check if paragraph contains <br> tags
          if (
            element.innerHTML.includes('<br>') ||
            element.innerHTML.includes('<br/>') ||
            element.innerHTML.includes('<br />')
          ) {
            // Handle paragraphs with <br> tags - split by <br> and process each line
            const lines = element.innerHTML.split(/<br\s*\/?>/i)
            lines.forEach((line, index) => {
              // Create a temporary element to parse the line
              const tempDiv = document.createElement('div')
              tempDiv.innerHTML = line
              result += processNode(tempDiv)

              // Add line break after each line except the last one
              if (index < lines.length - 1) {
                result += LINE_BREAK
              }
            })
          } else {
            // Regular paragraph - process normally
            result += processNode(element)
          }

          // Add line break after paragraph if it's not the last element
          if (element.nextElementSibling) {
            result += LINE_BREAK
          }
        } else {
          // Empty paragraph - add line break
          result += LINE_BREAK
        }
      } else if (tagName === 'br') {
        // Process <br> tags as line breaks
        result += LINE_BREAK
      } else if (tagName === 'table') {
        // Process table
        const rows = element.querySelectorAll('tr')
        rows.forEach((row, rowIndex) => {
          const cells = row.querySelectorAll('th, td')
          const rowContent = Array.from(cells)
            .map((cell) => cell.textContent?.trim() || '')
            .join(' | ')

          result += rowContent

          // Add line break after each row
          if (rowIndex < rows.length - 1) {
            result += LINE_BREAK
          }
        })

        // Add line break after the table
        if (element.nextElementSibling) {
          result += LINE_BREAK
        }
      } else if (tagName === 'img') {
        // Process image - preserve the image tag with its attributes
        const img = element as HTMLImageElement
        const src = img.getAttribute('src') || ''

        result += `<img src="${src}">`
      } else if (['strong', 'b', 'em', 'i', 'u', 'span'].includes(tagName)) {
        // Preserve formatting tags
        result += `<${tagName}>${processNode(element)}</${tagName}>`
      } else if (!['tr', 'th', 'td'].includes(tagName)) {
        // Process other elements recursively (skip table cells as they're handled by the table processor)
        result += processNode(element)
      }
    }
  })

  return result
}

console.log('value', value)
const html = convertTipTapToOnlyOfficeHtml(value)
console.log('html', html)
// @ts-ignore
window.connector.executeMethod('PasteHtml', [html])

Example input value before calling convertTipTapToOnlyOfficeHtml:
<p><strong>SEQUESTO BV</strong></p><p></p><p><em>Emiel Fleerackerslaan(MEL) 25</em><br><br><u>9120 Beveren-Kruibeke-Zwijndrecht</u></p>

Example html for ‘PasteHtml’:
<strong>SEQUESTO BV</strong><br><br><em>Emiel Fleerackerslaan(MEL) 25</em><br><br><u>9120 Beveren-Kruibeke-Zwijndrecht</u>

We expect that when pasting html with a
we would get a line break inside the same cell, however this makes it jump to a new cell. What we really want is af you would manually do alt + enter inside a cell, but this doesn’t work with
.

If we use the unicode character above in the code it will work fine visually in the spreadsheet editor, however on download of the file and opening it on your desktop the line breaks will be gone and this is probably because the unicode is not really picked up by excel and excel expects a \n instead.

When we do alt + enter in a cell I can see that it is represented by a \n by only office, but how can we paste html and have a proper \n in there which works visually on the spreadsheet editor, but also after downloading?

It is really not hard to reproduce, just paste html with the ‘PasteHtml’ method including a
html element, which should create a line break inside the cell and not move to a new cell.

test.xlsx (6.2 KB)

Kind regards,

Joachim

We are checking, please wait

Any news on this?

Kind regards,

Joachim

Not yet, I’ll share as soon as I’ve got news

Hi DmitriiV,

I can’t imagine that this takes 10 days to test?
Please provide is with more info as our customers are waiting on this

Kind Regards

Hello @LaurensSequesto,
Sorry for the delay, we are still looking into it and will inform you as soon as there is any update. We’ve seen that you’ve created a ticket regarding the issue; we will respond there with priority

Hello @LaurensSequesto

I was informed that his us expected behavior with usage of PasteHTML method. If you want to insert your content into a single cell, then you need to open it first.