diff --git a/plugins/openoffice/openoffice-write.c b/plugins/openoffice/openoffice-write.c
index cdd7c57..2af587b 100644
--- a/plugins/openoffice/openoffice-write.c
+++ b/plugins/openoffice/openoffice-write.c
@@ -3534,20 +3534,58 @@ odf_sheet_objects_get (Sheet const *sheet, GnmCellPos const *pos)
 	return res;
 }
 
+enum {
+	RF_CELL = 1,
+	RF_PAGEBREAK = 2,
+	RF_OBJECT = 4,
+	RF_STYLE = 8
+};
+
 static void
 odf_write_content_rows (GnmOOExport *state, Sheet const *sheet, int from, int to,
 			G_GNUC_UNUSED int col_from, G_GNUC_UNUSED int col_to, int row_length,
-			GSList **sheet_merges, GnmPageBreaks *pb, G_GNUC_UNUSED GnmStyle **col_styles)
+			GSList **sheet_merges, GnmPageBreaks *pb, GnmStyle **col_styles)
 {
 	int col, row;
-	GnmRange fake_extent;
 	GPtrArray *all_cells;
 	guint cno = 0;
+	guint8 *row_flags;
+
+	row_flags = g_new0 (guint8, gnm_sheet_get_max_rows (sheet));
+
+	/* FIXME: We need to mark rows that have objects.  */
+
+	for (row = from; row < to; row++) {
+		if (gnm_page_breaks_get_break (pb, row) != GNM_PAGE_BREAK_NONE)
+			row_flags[row] |= RF_PAGEBREAK;
+	}
+
+	{
+		GnmRange fake_extent;
+		unsigned ui;
+		range_init_rows (&fake_extent, sheet, from, to - 1);
+		all_cells = sheet_cells ((Sheet*)sheet, &fake_extent);
+		for (ui = 0; ui < all_cells->len; ui++) {
+			GnmCell *cell = g_ptr_array_index (all_cells, ui);
+			row_flags[cell->pos.row] |= RF_CELL;
+		}
+		/* Add a NULL to simplify code.  */
+		g_ptr_array_add (all_cells, NULL);
+	}
 
-	range_init_rows (&fake_extent, sheet, from, to - 1);
-	all_cells = sheet_cells ((Sheet*)sheet, &fake_extent);
-	/* Add a NULL to simplify code.  */
-	g_ptr_array_add (all_cells, NULL);
+	{
+		guint8 *non_defaults_rows =
+			sheet_style_get_nondefault_rows (sheet, col_styles);
+		for (row = from; row < to; row++)
+			if (non_defaults_rows[row])
+				row_flags[row] |= RF_STYLE;
+		g_free (non_defaults_rows);
+	}
+
+	for (row = from; row < to; row++) {
+		if (row == from || row_flags[row] != row_flags[row - 1])
+			g_printerr ("Row %d: %d\n", row, row_flags[row]);
+	}
 
 	for (row = from; row < to; row++) {
 		ColRowInfo const *ci = sheet_row_get (sheet, row);
@@ -3558,7 +3596,7 @@ odf_write_content_rows (GnmOOExport *state, Sheet const *sheet, int from, int to
 
 		pos.row = row;
 
-		if (gnm_page_breaks_get_break (pb, row) != GNM_PAGE_BREAK_NONE)
+		if (row_flags[row] & RF_PAGEBREAK)
 			gsf_xml_out_simple_element (state->xml,
 						    TEXT "soft-page-break",
 						    NULL);
@@ -3566,7 +3604,7 @@ odf_write_content_rows (GnmOOExport *state, Sheet const *sheet, int from, int to
 		gsf_xml_out_start_element (state->xml, TABLE "table-row");
 		write_row_style (state, ci, sheet);
 
-		for (col = 0; col < row_length; col++) {
+		if (row_flags[row]) for (col = 0; col < row_length; col++) {
 			GnmCell *current_cell;
 			GnmRange const	*merge_range;
 			GSList *objects;
@@ -3629,6 +3667,7 @@ odf_write_content_rows (GnmOOExport *state, Sheet const *sheet, int from, int to
 	}
 
 	g_ptr_array_free (all_cells, TRUE);
+	g_free (row_flags);
 }
 
 static void
diff --git a/src/sheet-style.c b/src/sheet-style.c
index 035c30c..daf84f3 100644
--- a/src/sheet-style.c
+++ b/src/sheet-style.c
@@ -2164,6 +2164,51 @@ sheet_style_is_default (Sheet const *sheet, const GnmRange *r, GnmStyle **col_de
 	return user.res;
 }
 
+struct cb_get_nondefault {
+	guint8 *res;
+	GnmStyle **col_defaults;
+};
+
+static void
+cb_get_nondefault (GnmStyle *style,
+		   int corner_col, G_GNUC_UNUSED int corner_row,
+		   int width, G_GNUC_UNUSED int height,
+		   GnmRange const *apply_to, gpointer user_)
+{
+	struct cb_get_nondefault *user = user_;
+	int i;
+
+	/* The given dimensions refer to the tile, not the area. */
+	width = MIN (width, apply_to->end.col - corner_col + 1);
+	height = MIN (height, apply_to->end.row - corner_row + 1);
+
+	for (i = 0; i < width; i++) {
+		if (style != user->col_defaults[corner_col + i]) {
+			int j;
+			for (j = 0; j < height; j++)
+				user->res[corner_row + j] = 1;
+			break;
+		}
+	}
+}
+
+guint8 * 
+sheet_style_get_nondefault_rows (Sheet const *sheet, GnmStyle **col_defaults)
+{
+	struct cb_get_nondefault user;
+	GnmRange r;
+
+	range_init_full_sheet (&r, sheet);
+
+	user.res = g_new0 (guint8, gnm_sheet_get_max_rows (sheet));
+	user.col_defaults = col_defaults;
+
+	foreach_tile (sheet->style_data->styles,
+		      sheet->tile_top_level, 0, 0, &r,
+		      cb_get_nondefault, &user);
+
+	return user.res;
+}
 
 struct cb_most_common {
 	GHashTable *h;
diff --git a/src/sheet-style.h b/src/sheet-style.h
index 4c1670d..0330352 100644
--- a/src/sheet-style.h
+++ b/src/sheet-style.h
@@ -47,6 +47,9 @@ unsigned int sheet_style_find_conflicts (Sheet const *sheet, GnmRange const *r,
 void	 sheet_style_get_extent		(Sheet const *sheet, GnmRange *r);
 void	 sheet_style_get_nondefault_extent (Sheet const *sheet, GnmRange *extent,
 					    const GnmRange *src, GnmStyle **col_defaults);
+guint8 * sheet_style_get_nondefault_rows (Sheet const *sheet,
+					  GnmStyle **col_defaults);
+					   
 gboolean sheet_style_is_default         (Sheet const *sheet, const GnmRange *r, GnmStyle **col_defaults);
 void     style_row_init			(GnmBorder const * * *prev_vert,
 					 GnmStyleRow *sr, GnmStyleRow *next_sr,
