Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

dantastic

macrumors 6502a
Original poster
Jan 21, 2011
572
678
I'm trying to read a spreadsheet worth of text and save NSAttributed string into a NSDictionary. The pasteboard guide got me going as far as

Code:
NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
	NSArray *classes = [[NSArray alloc] initWithObjects:[NSAttributedString class], [NSString class], nil];
	NSDictionary *options = [[NSDictionary alloc] init];
	NSArray *items = [pasteBoard readObjectsForClasses:classes options:options];

In items I have one single item of the type NSAttributedString.

I was somewhat hoping that each cell of the spreadsheet would turn into one attributedstring, magic, eh :)

Realizing that is not the case I'm trying to get my head around the data I actually have access to. I have tried to have only a very small bit of text in my clipboard (one cell worth). This allow me to get the one attributedstring I was hoping for.

The problem is that that attributedstring is not writing to disk properly.
Code:
NSAttributedString *str = [items lastObject];
	NSDictionary *dict = @{@"testString": str};
	if (![dict writeToFile:@"/Users/dantastic/Desktop/out.plist" atomically:NO]) {
		NSLog(@"Fail...");
	}

If I hand craft an attributedstring it does save to disk so I'm thinking the one I read from clipboard is containing more than can be serialized or something like that.

My theory at this point is that I am getting one huge NSAttributedString from the clipboard that I will have to chop down to size somehow?

Anyone able to point me in the right direction here?
 

dantastic

macrumors 6502a
Original poster
Jan 21, 2011
572
678
I should probably add that I missed the crucial conversion to NSData before storing the NSAttributedString into my dictionary.

Code:
NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
	NSArray *classes = [[NSArray alloc] initWithObjects:[NSAttributedString class], [NSString class], nil];
	NSDictionary *options = [[NSDictionary alloc] init];
	NSArray *items = [pasteBoard readObjectsForClasses:classes options:options];
	NSAttributedString *string = [items lastObject];
	NSError *err;
	NSDictionary *doc = @{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType};
	NSData* myStringData = [string dataFromRange:NSMakeRange(0, string.length) documentAttributes:doc error:&err];
	if (!myStringData) {
		NSLog(@"%@", err);
	}

I still haven't been able to figure out how to split a large import of strings though
 
Last edited:

chown33

Moderator
Staff member
Aug 9, 2009
10,750
8,422
A sea of green
Please explain what you want to do with the data once it's been extracted. Do you intend to calculate with it? Tabulate it? Show it in a display? Something else?


On the subject of extracting data, the first thing I'd do is look for a more suitable pasteboard data type than NSAttributedString. There is a tabular text type that looks promising. From the NSPasteboard class reference:

NSPasteboardTypeTabularText
An NSString object containing tab-separated fields of text.

You'd still have to work out how rows are delimited (newlines?), but tab-separated fields seems like a good start.

A single cell from the spreadsheet seems unlikely to show anything useful in a tabular-text format. I suggest a 3-column by 2-row selection of cells. If there are tabs between cells in a row, and newlines between rows, that's something to go on.


If you don't have tabular text or any other useful form, then remember that an NSAttributedString isn't monolithic. It's made from smaller parts. So break it down into those parts, and then break those down into their smaller parts, and so on.

I'd start breaking it down in two separate ways. The text parts first, then the attribute parts.

First, get the NSString from the NSAttributedString (the string method). Then make all the characters visible, and see if there are any obvious delimiters or anything.

Also look at the plain non-attributed NSString type from the pasteboard. Does it provide exactly the same text string as the string from the NSAttributedString?

Second, what attributes does the NSAttributedString have? Again, break it down into smaller pieces. What attributes does the first character have? Are any of them custom attributes, or are they only the standard attributes? Refer to the NSAttributedString reference docs to learn which attributes are standard, and how to get a set of attributes.

Once you have a way to look at attributes on single characters, start looking at the places where attributes change. That is, is there a change in attributes that happens when a cell boundary is crossed? Is this change reliable, or does it happen when there's any change in style within a single cell?

In other words, once you've broken down the attributes into single-character sets, start putting them back together into runs of attributes, and see if there's something you can discern that consistently occurs at cell boundaries.
 

dantastic

macrumors 6502a
Original poster
Jan 21, 2011
572
678
The goal is to create a NSDictionary with localized formatted strings for use within an iOS app. iOS can't create NSAttributedStrings from RTF data yet but Mac can so this here is a small tool to just cater for that.

So all the data I need to import is actually in a Numbers spreadsheet in front of me. Googling "numbers" with anything at all isn't helpful so I don't know if I might be able to bypass the pasteboard as an intermediate and just access the spreadsheet direct, that would be great.

I did select a few cells, import them and just drew them out to a view and the strings are clearly separated into blocks or paragraphs. So I think I will have to go looking for the paragraphs for separation.
 

chown33

Moderator
Staff member
Aug 9, 2009
10,750
8,422
A sea of green
The goal is to create a NSDictionary with localized formatted strings for use within an iOS app. iOS can't create NSAttributedStrings from RTF data yet but Mac can so this here is a small tool to just cater for that.

I still don't understand what the iOS app will be doing with the data, once it's obtained it in a form it can use.

Is the iOS app just going to display the spreadsheet? Is it going to allow editing? Is it going to do some data reduction or other calculations using values in the data?

If the iOS app is just going to display some data, then consider using HTML. You can display HTML in a UIWebView on iOS, and HTML's styling and presentation capabilities are well-known and quite powerful. An NSDictionary in some proprietary format will still need to be parsed on iOS side. Unless you already have a parser and a clear definition of the NSDictionary data, I don't see how that format gives you anything immediately usable on iOS.

Regarding the conversion into HTML, there is a command-line tool called 'textutil' that can convert between RTF, RTFD, HTML, plain text, and some other formats. So if you have a spreadsheet in Numbers, and export it as RTF, you can then apply 'textutil' to produce the HTML.
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/textutil.1.html

So all the data I need to import is actually in a Numbers spreadsheet in front of me. Googling "numbers" with anything at all isn't helpful so I don't know if I might be able to bypass the pasteboard as an intermediate and just access the spreadsheet direct, that would be great.
I'm not sure what you mean by "access the spreadsheet direct". Do you mean reading the file directly, without the use of Numbers.app? Or do you mean telling Numbers.app to open the spreadsheet, and then scripting various actions using AppleScript from outside Number.app itself.
 

dantastic

macrumors 6502a
Original poster
Jan 21, 2011
572
678
This is a step up from the built in localization. on iOS to make use of the built in localization I can only localize NSStrings. If I then want to make a formatted string (NSAttributedString) out of it it's actually quite tedious and it's very difficult to manage this across translations.

However, I have a spreadsheet with localizations where the localized strings are already formatted. So my spreadsheet have the localization keys on the y axis and the locales on the x axis. This way I can pull ready to use attributes strings straight from a dictionary rather than having to mess about doing this in code.

I have now come to a solution I'm very happy with. I am creating the dictionary structure I was after and I'm exporting to a plist.

The key is to find the NSTextTableBlock inside the NSAttributedString from clipboard. The text table block allows traversing the actual table by individual blocks and I can query each block for their row and column. Then I can extract an attributedString from that one cell and use.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.