Skip to main content
Inspiring
October 15, 2019
Answered

Object is invalid error after changing contents of characters

  • October 15, 2019
  • 11 replies
  • 1337 views

Hi,

 

It doesn't seem to be a problem changing a range of characters of a paragraph with ".contents = someString". A small test script confirmed this. But in my main script, immediately after I have used this line in a while loop:

 

textObj.characters.itemByRange(p_start +1, p_start + textStr[p].length).contents = dataStr[p];

 

the textObj becomes an invalid object.

(The task is to replace ranges of characters within a paragraph with a translation.)

 

Any clue?

Thanks!

 

 

This topic has been closed for replies.
Correct answer Sunil Yadav

The reason behind you object being in valid because after changing text, range of those characters are varying, and you are storing all those range value for the first time only.

So after after first change other ranges are getting varried, but you still have the old range.

This is the reason of you variable becoming invalid.

 

Best

Sunil

11 replies

Sunil Yadav
Brainiac
October 16, 2019

Hi AnotherFrank,

As Uwe Laubender said: without a sample InDesign document at hand it's very hard to tell what's going wrong.

That's also my impression. But majorly looking at your logic and code, you variable of range of character only can go invalid if your ranges doesn't exists.

As you said you made those changes and it is working fine, what else can be better...

 

Best

Sunil

Inspiring
October 15, 2019

Hi Uwe,

 

Well, after Sunil suggested to refresh the variable after adjusting the range of characters, I basically created a new variable (newObj) keeping the old one intact (textObj) and updated the new one right after I changed the character range. And that seemed to work. So, the code above includes that change already and is therefore working fine.

 

Thanks!

Frank

Community Expert
October 15, 2019

Hi Frank,

without a sample InDesign document at hand it's very hard to tell what's going wrong.

 

Regards,
Uwe Laubender

( ACP )

Inspiring
October 15, 2019

Hi Uwe,

 

Thanks for looking into it as well.

 

Just so I don't speak in riddles, I'm pasting the code below. This is for translations. My first script extracts all stories,paragraphs from the indd, while replacing anchored objects with [a] (so that they show up later in Excel) but ignoring regular spaces, anchored obects and table markers before and after each paragraph. This way, I have a "cleaner" text export for translators. After the text got translated, the code below imports the translation via txtData where I also stored story IDs, paragraph and table indexes to find the right place for each paragraph text. Since the indd could have anchored objects that need to be kept, I'm basically splitting each paragraph into arrays if they contain anchored object markers (\uFFFC). And then each element of the array gets filled with the appropriate text from the txtData.

 

The code below works with a simple test file using tables and many anchored objects, but might break with more complex documents. So it's work in progress. The change I did after Sunil's response is that I introduced the variable "newObj" to keep the original textObj alone.

 

Curious to hear if my approach is too complicated, the whole thing would be much easier if I could just ignore anchored objects, but I can't.

 

	for (var i = txtData.length - 1; i > 0; i--) {
		if (txtData[i][7] != "" && txtData[i][7] != " " && txtData[i][7] != "[a]" && txtData[i][8] != "[MISSING]") {
			
			if (txtData[i][3].toString().substring(0,4) == "Text") {
				textObj = myStories.itemByID(Number(txtData[i][1])).paragraphs[Number(txtData[i][2])];
			} else if (txtData[i][3].toString().substring(0,5) == "Table") {
				var tableNo = txtData[i][3].toString();
				tableNo = tableNo[tableNo.length -1];
				textObj = myStories.itemByID(Number(txtData[i][1])).tables[tableNo].cells.item(txtData[i][5].toString() + ":" + txtData[i][4].toString()).paragraphs[Number(txtData[i][2])];
			}
		
			//^a, Spaces, Returns und Tabellen zu Beginn und am Ende des Absatzes ignorieren ++++++++++ Table 0016 +++ aObj uFFFC ++++ Return 000D
			textStr =  textObj.contents.toString();
			var start = 0, end = textStr.length -1;
			while (textStr[start] == "\uFFFC" || textStr[start] == " " || textStr[start] == "\u0016") {
				start++;
			}
			while (textStr[end] == "\uFFFC" || textStr[end] == " " || textStr[end] == "\u000D" || textStr[end] == "\u0016") {
				end--;
			}
			newObj = textObj.characters.itemByRange(start,end);
			textStr = textStr.substring(start,end +1);

			if (textStr.indexOf("\uFFFC") != -1) {
				//TODO: Textbausteine aufsplitten
				var last = textStr.length;
				
				//Verankerte Objekte prüfen
				if ((newObj.contents.toString().match(/\uFFFC/g) || []).length != (txtData[i][8].toString().match(/\[a\]/g) || []).length) {
					$.writeln("Anchored Objects mismatch in row " + i);
				} else {
					var p_count = (txtData[i][8].toString().match(/\[a\]/g) || []).length +1;
				}

				textStr = textStr.split("\uFFFC");
				dataStr = txtData[i][8].toString().split("[a]");

				for (var p = p_count -1; p >= 0; p--) {
					p_start = newObj.contents.toString().lastIndexOf("\uFFFC", last);
					newObj.characters.itemByRange(p_start +1, p_start + textStr[p].length).contents = dataStr[p];
					newObj = textObj.characters.itemByRange(start,start + newObj.characters.length -1);
					last = last - textStr[p].length -2;
				}
			} else {
				newObj.contents = txtData[i][8];
			}
		}
	}
Community Expert
October 15, 2019

Go ahead using "Insert/Edit code sample" function of the editor. It's the only available and most reasonable thing to do. No better tool for now. Think, we have to live with this.

 

Regards,
Uwe Laubender

( ACP )

Inspiring
October 15, 2019

Ok, so what's the best way to paste code in here? I tried the insert/edit code sample but the text looks too big, and images are scaled down too much in size so the code isn't legible anymore.

Community Expert
October 15, 2019

Hi Frank,

always use the big blue Reply button. Thanks!

Nested replies that are added with the other reply buttons are a pest.

 

FWIW: Your reply was truncated.

 

Uwe Laubender

( ACP )

Community Expert
October 15, 2019

Hi Frank,

in principle you could address the story every time you iterate the loop without using the variable textObj. That could work. Or not. It depends if we are talking of an array or of a collection when it comes to textObj. A collection will or should be updated automatically, an array will not be updated automatically.

 

Sunil and I cannot know what's exactly stored in your variable textObj at runtime.

"stories.itemByID[…].paragraphs[…]" unfortunately is no help.

( Could also be that there are no paragraphs in a story at all. Then the story consists of a single insertion point only. )

 

What's your while condition?

 

Regards,
Uwe Laubender

( ACP )

 

Inspiring
October 15, 2019

[Moved message one level higher]

Sunil Yadav
Sunil YadavCorrect answer
Brainiac
October 15, 2019

The reason behind you object being in valid because after changing text, range of those characters are varying, and you are storing all those range value for the first time only.

So after after first change other ranges are getting varried, but you still have the old range.

This is the reason of you variable becoming invalid.

 

Best

Sunil

Inspiring
October 15, 2019
Understood, I changed the code by using a new variable for the changed character range and used to original to refresh it which worked fine. Thanks much!
Sunil Yadav
Brainiac
October 15, 2019

can you show me your full code and file screenshot for better understanding?

Then it would be much easier to help.

 

Sunil