Category Archives: Android

Posts on Android development

Examples of using Excel from C#

To begin using Excel from C# we should right-click on References in Solution Explorer or Project/Add Reference on File Menu and add a Reference to Excel (Microsoft Excel Object Library 12.0)

The following methods are not fully mine, they are the modification of code, taken from Internet.

1. Example of opening a definite Worksheet for future use.

Let’s assume that you have AAA.xls file previously created on C:\.

// Some additional namespaces
using System.IO;
using Excel = Microsoft.Office.Interop.Excel;

// Common variables for different methods
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;

private void OpenExcelWorksheet()
{

object misValue = System.Reflection.Missing.Value;

// Specify a "currently active folder"
string activeDir = @"c:\";

//Create a newPath - the Path to Excel file
string newPath = System.IO.Path.Combine(activeDir, "AAA");

// Create the subfolder
// System.IO.Directory.CreateDirectory(newPath);

// Create a new file name.
string newFileName = "AAA.xls";

// Combine the new file name with the path
newPath = System.IO.Path.Combine(newPath, newFileName);

xlApp = new Excel.Application();
xlWorkBook = xlApp.Workbooks.Open(newPath, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);

}

2. Inserting data to Excel Worksheet

The following method inserts data in 2 column array “citations” to Excel worksheet to the lines from fromNum to toNum and columns B and C.


private void InsertToExcel(int fromNum, int toNum)
{
string fromRange, toRange;
fromRange = "B" + fromNum.ToString();
toRange = "C" + toNum.ToString();

try
{

xlApp.Visible = true;

//Fill A1:B20 with an array of values (First and Last Names).
xlWorkSheet.get_Range(fromRange, toRange).Value2 = citations;

//Make sure Excel is visible and give the user control
//of Microsoft Excel's lifetime.
xlApp.Visible = true;
xlApp.UserControl = true;
}
catch (Exception theException)
{
String errorMessage;
errorMessage = "Error: ";
errorMessage = String.Concat(errorMessage, theException.Message);
errorMessage = String.Concat(errorMessage, " Line: ");
errorMessage = String.Concat(errorMessage, theException.Source);

MessageBox.Show(errorMessage, "Error");
}
}

References:

  1. http://csharp.net-informations.com/excel/csharp-open-excel.htm
  2. http://msdn.microsoft.com/en-us/library/as2f1fez.aspx

Creation of files in a given folder programmatically using Visual Basic Script (VBScript)

If a user must create, for instance, 20 files with names 1.tex, 2.tex, 3.tex, …, 20.tex, he will probably do it manually. Even the use of Total Commander with its hot key Shift+F4 for creation of files will not save you from the boring and stupid work. But a programmer is not a user and you can write the following Visual Basic Script (VBScript) with file name, for example, “CreateFilesScript.vbs”.

———————————————————————————

'(C) Author: Denis Kutlubaev, Alwawee Company, Moscow, 2011
'This script creates files with names 25.tex to 36.tex in a given folder
'folderPath - path to folder where files must be created
'fileName - generated file name
'filePathAndName - generated full path and file name
'start and stopIndex - numbers to start and stop file naming and creation

Dim folderPath, fileName, filePathAndName
Dim fileNumber, i
Set FSO = CreateObject("Scripting.FileSystemObject")

folderPath = "c:\Documents and Settings\wzbozon\Рабочий стол\LaTeX\Lessons\"

For i = 25 To 36
fileNumber = i
fileName = CStr(fileNumber) & ".tex"
filePathAndName = folderPath & fileName
FSO.CreateTextFile(filePathAndName)
Next

———————————————————————————

It is noteworthy that in Visual Basic Script there are some restrictions. For example, the loop

For i = 25 To 36

cannot be unhardcoded.

Also, you cannot define step for loop, it is always 1.

In this line

fileName = CStr(fileNumber) & ".tex"

there is a concatenation of a string, produced by CStr operator from a number and a file extension.

If you write a VBScript, you will wish to debug it. To debug it, write in a command line:
wscript //X CreateFilesScript.vbs

After this you can choose Visual Studio as a default debugger for VBScript and you will catch the line, where the script fails. Unfortunately, without much information about the bug.

Some useful links:

  1. http://msdn.microsoft.com/en-us/library/te2585xw(v=vs.80).aspx – Concatenation of strings in VBScript
  2. http://www.tizag.com/vbscriptTutorial/vbscriptforloop.php – Loops in VBScript
  3. http://www.script-coding.com/ – Good source for script writing (in Russian)

Случайная расстановка записей в Microsoft Excel 2007

Если у вас возникла задача: случайно расставить записи в Excel, не нужно писать программу на VBA. Есть более простой метод:


1. Каждой записи приписываем номер. Сделать это легко. Ставим 1, 2 номера на первые две записи и далее просто растягиваем на все записи. Или выделяем ячейки с этими номерами и нажимаем дважды на уголок, все остальные записи пронумеруются.


2. Пишем функцию для ячейки в соседнем столбце. Например =SIN(наша ячейка с порядковым номером). Аналогично растягиваем эту функцию на все записи. Должно получиться что-то подобное (чтобы увеличить картинку, нажмите на нее, затем вернитесь, нажав назад в браузере):



3. Нажимаем на вкладку “Данные” в Ribbon или Главном меню. Далее в разделе “Сортировка и фильтр” нажимаем “Сортировка”. Далее в появившемся окне выбираем столбец со значениями нашей функции. На рисунке показано, где эта кнопка находится:



4. Записи отсортируются и получится случайное их распределение. Теперь можно их снова пронумеровать. После сортировки мы получим следующее распределение:


Обновление TableView из Detail View

Иногда возникает ситуация, когда нужно изменить набор или содержание Table View, находясь в Detail View, то есть в дочернем View для данного Table View. При этом известно, что ViewDidLoad уже не запустится после того, как произойдет Dismiss дочернего экрана. Для решения этой проблемы нужно писать код по обновлению и загрузке Table View не в ViewDidLoad, а в ViewWillAppear. Например,

- (void)viewWillAppear:(BOOL)animated {
favoritesEntries = [[NSMutableArray alloc] init];
[self grabFavs];
[favoritesTable reloadData];
[super viewWillAppear:animated];
}

Здесь функция grabFavs заполняет каждый раз заново массив favoritesEntries элементами, которые затем используются в Table View. Функция reloadData – это стандартная функция, которая перегружает Table View.

Полезные горячие клавиши для MacBook

BootCamp в Windows:

Shift+Fn+F11 – Print Screen экрана, если ваши функциональные клавиши управляют железом

Shift+F11 – Print Screen экрана, если ваши функциональные клавиши ведут себя как обычные функциональные клавиши обычных клавиатур

То же самое+Alt – Print Screen активного окна

 

в Mac Os X:

http://graphicssoft.about.com/od/screencapturemac/ht/macscreenshot.htm – Все о скриншотах в Mac Os X

Command+Shift+3 – Скриншот всего экрана будет автоматически сохранен на рабочем столе в формате PNG

Command-Control-Shift-3 – Скриншот всего экрана, он будет помещен в буфер обмена

Command+Shift+4 – Скриншот части экрана, сохраняется в формате PNG

Command+Shift+4, then press the Spacebar – Скриншот определенного окна, причем если перевести курсор на другое окно, то выделится оно. То есть окно не обязательно должно быть активным, когда вы нажимаете это сочетание клавиш.

То же самое + Control –  Скриншот сохраняется в буфере обмена, а не на рабочем столе.

Cmd+I – Открыть свойства файла, например, чтобы переименовать его

Alt+Cmd+M – Свернуть все окна

Cmd+M – Свернуть окно

Shift+Cmd+A – Открыть папку приложений

Cmd+N – Новое окно Finder

Alt+Shift+Cmd+Esc(3 sec) – Принудительное завершение программ

Shift+Cmd+U – Окно служебных программ

Alt+Cmd+W– Закрыть все окна

Cmd+W – Закрыть окно

Cmd+1,2,3,4 – Переключение между режимами просмотра(виды) в Finder соответственно значки, список, колонки, Cover Flow

Shift+Cmd+N – Новая папка

Shift+Cmd+F – Открыть поиск по всему проекту(в XCode)

fn+Backspace – Аналог кнопки Delete, стирает текст справа по направлению к курсору

Shift+Cmd+L – В Interface Builder вызов Library

Ctrl+Cmd+O – В XCode вызов органайзера

Shift+Cmd+I – в Interface Builder вызов Inspector

Решение проблемы с отображением Default.png на девайсе

Default.png – это стандартная заставка в приложениях для iPhone, которая отображается во время загрузки приложения. Часто бывает такое, что на симуляторе она отображается нормально, а когда тестируешь на девайсе, не отображается. Причиной этого может быть то, что Default.png сделан простой конвертацией из *.jpg. Девайс требует настоящий *.png формат. Хотя в интернете в некоторых блогах пишут, что помогает пресловутый Clean All Targets + Build & Run. Также эту проблему можно обойти следующим образом: в XCode выделите Default.png, нажмите сочетание клавиш command+I (вызвать свойства объекта). Затем выберите в выпадающем списке File Type элемент image.jpeg.

Полезные ссылки для разработчиков iOS

Рекоммендую:

http://developer.apple.com/ – Главный сайт любого разработчика

http://developer.apple.com/devcenter/ios/index.action – Центр разработки под iOS

http://developer.apple.com/membercenter/index.action – Информация для зарегистрированных разработчиков

https://developer.apple.com/library/ios/navigation/ – Библиотека по iOS

https://itunesconnect.apple.com/ – iTunes Connect, инструменты управления контентом разработчика в AppStore

http://www.touchdev.ru/ – Блог других разработчиков

http://touchdev.ru/documents/1208 – Обзор рынка приложений

http://dblog.com.au/iphone-development-tutorials/iphone-sdk-tutorial-reading-data-from-a-sqlite-database/ – Обучение работе с SQLite

http://dblog.com.au/general/iphone-sdk-tutorial-building-an-advanced-rss-reader-using-touchxml-part-1/ – Обучение работе с XML, Table View, RSS и т.д.

http://www.tbxml.co.uk/TBXML/TBXML_Free.html – Облегченная библиотека XML

http://habrahabr.ru/tag/iPhone%20SDK/ – Блог с новостями и статьями вводного характера

http://www.iphonesdkarticles.com/ – Блог других разработчиков

http://www.iphonedevsdk.com/forum/ – форум по iPhone SDK

http://www.iphonedevsdk.com/forum/iphone-sdk-tools-utilities/ – Подраздел форума по iPhone SDK Utilities

http://www.iphones.ru/ – Новости и советы по iPhone/iPad

http://apples-store.ru/ – Б/у и новые девайсы Apple

http://stackoverflow.com/questions/tagged/iphone – Q&A для программистов iPhone

http://seanmurph.com/weblog/ – Блог другого разработчика

http://www.techotopia.com/index.php/IPhone_App_Development_Essentials – Techotopia – это библиотека бесплатных онлайн книг по IT, данная ссылка ведет к разделу iPhone

Загрузка данных с сайта в собственную базу

Допустим, вам надо перенести определенные данные с какого-то сайта в свою базу данных в красивом, структурированном виде. Но вы не хотите сидеть и копи-пастить в Excel эти данные. Тогда может помочь следующий метод. Он основан на использовании C# приложения для загрузки, очистки и парсинга HTML и дальнейшей загрузке данных в Excel программно.

Для пользования данным методом нужно владеть языком C#, так как мой код надо всегда затачивать под каждый сайт.

1. Открываем среду разработки на C#(Я пользуюсь MS Visual Studio 2010 Ultimate). Создаем новый проект с простой формой:

В адресе URL мы введем страницу, из которой нужно получить контент при нажатии на кнопку. При этом автоматически откроется Excel 2007 и в него занесутся данные – этот контент.

2. Нажимаем правой кнопкой по References под названием проекта в Solution Explorer. Выбираем Add Reference. Далее во вкладке COM находим и выбираем компоненту Microsoft Excel 12.0 Object Library. Ссылки на эту компоненту понадобятся для автоматической загрузки данных в Excel.

3. Редактируем список пространств имен:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Linq;
using System.Web;
using System.IO;
using System.Net;
using System.Collections;
using System.Collections.Specialized;
using System.Configuration;
using Excel = Microsoft.Office.Interop.Excel;
using System.Reflection;

4. Пишем код для кнопки.

private void button1_Click(object sender, EventArgs e)
{
string OldText, NewText, PossibleRefText, RefText, textOfCitation, authorOfCitation;
strURL = textBox1.Text;
OldText = GetHtmlFromUrl(strURL);
int begin, begin0, i;
int end;
int length;
int lastindex;
int newindex;
int indexOfClosingTag, difference, indexOfHref;
int indexofrefbegin, indexofspanbegin, indexOfAuthorEnd, indexOfAuthorBegin, indexOfAuthorBegin0;
RefText = "<a href";
newindex = OldText.IndexOf("<p class=\"data\">");
begin = OldText.IndexOf("<p class=\"data\">");
lastindex = OldText.LastIndexOf("<p class=\"data\">");
OldText = OldText.Remove(0, newindex);
i = 0;
while (!(newindex == (-1)))
{
i = i + 1;
begin0 = OldText.IndexOf("<p class=\"data\">");
begin = OldText.IndexOf("<p class=\"data\">") + 16;
indexofrefbegin = begin;
end = OldText.IndexOf("</p>");
length = end - begin;
if (length < 0)
{
break;
}
textOfCitation = OldText.Substring(begin, length);
OldText = OldText.Remove(0, end + 4);

indexOfAuthorBegin0 = OldText.IndexOf("class=\"author\"");
OldText = OldText.Remove(0, indexOfAuthorBegin0);
indexOfAuthorBegin0 = OldText.IndexOf("class=\"author\"");
indexOfHref = OldText.IndexOf("href=");
difference = indexOfHref - (indexOfAuthorBegin0 + 15);
if (difference < 5 && difference >= 0)
{
indexOfClosingTag = OldText.IndexOf(">");
length = indexOfClosingTag - indexOfAuthorBegin0 - 14;
OldText = OldText.Remove(indexOfAuthorBegin0 + 15, length);
}
indexOfAuthorBegin = OldText.IndexOf("class=\"author\"") + 15;

indexOfAuthorEnd = OldText.IndexOf("<");
length = indexOfAuthorEnd - indexOfAuthorBegin;
if (length < 0)
{
break;
}

authorOfCitation = OldText.Substring(indexOfAuthorBegin, length);
OldText = OldText.Remove(0, indexOfAuthorEnd + 1);

//Literal1.Text = Literal1.Text + " " + i.ToString() + ". " + textOfCitation + " " + "(" + authorOfCitation + ")" + "</br>";
textOfCitation = cleanFromBr(textOfCitation);
textOfCitation = cleanFromQuot(textOfCitation);
citations[i - 1, 0] = textOfCitation;
citations[i - 1, 1] = authorOfCitation;

}

//Добавляем массив цитат в Excel
InsertToExcel();

//  движок для википедии
//{
//    string OldText, NewText, PossibleRefText, RefText;
//    strURL = TextBox1.Text;
//    OldText = GetHtmlFromUrl(strURL);
//    int begin;
//    int end;
//    int length;
//    int lastindex;
//    int newindex;
//    int indexofrefbegin, indexofspanbegin;
//    RefText = "<p class=\"data\">";
//    newindex = OldText.IndexOf(RefText);
//    begin = OldText.IndexOf(RefText);
//    lastindex = OldText.LastIndexOf("</p>");
//    while (!(newindex == (-1)))
//    {
//        begin = OldText.IndexOf(RefText) + 16;
//        end = OldText.IndexOf("</p>");
//        length = end - begin;
//        NewText = OldText.Substring(begin, length);
//        newindex = OldText.IndexOf(RefText);
//        Literal1.Text = Literal1.Text + NewText;
//    }
//}

}

Здесь мы сначала запрашиваем HTML в текстовую строку с помощью функции GetHtmlFromUrl. Затем мы эту текстовую строку обрабатываем, удаляя все ненужное, а нужное занося в массив. Затем добавляем получившийся массив в Excel с помощью функции InsertToExcel().

5. Пишем дополнительный вспомогательный код с функциями, которые использовались в коде для кнопки:


private string cleanFromBr(string text)
{
int indexOfStart, indexOfEnd;
indexOfStart = text.IndexOf("<br/>") - 1;
while (indexOfStart != -2)
{
indexOfEnd = indexOfStart + 6;
text = text.Remove(indexOfStart, 6);
text = text.Insert(indexOfStart, " ");
indexOfStart = text.IndexOf("<br/>") - 1;
}
return text;
}

private string cleanFromQuot(string text)
{
int indexOfStart, indexOfEnd;
indexOfStart = text.IndexOf("&quot;");
while (indexOfStart != -1)
{
indexOfEnd = indexOfStart + 6;
text = text.Remove(indexOfStart, 6);
text = text.Insert(indexOfStart, "\"");
indexOfStart = text.IndexOf("&quot;");
}
return text;
}

private void InsertToExcel()
{
Excel.Application oXL;
Excel._Workbook oWB;
Excel._Worksheet oSheet;
Excel.Range oRng;

try
{
//Start Excel and get Application object.
oXL = new Excel.Application();
oXL.Visible = true;

//Get a new workbook.
oWB = (Excel._Workbook)(oXL.Workbooks.Add(Missing.Value));
oSheet = (Excel._Worksheet)oWB.ActiveSheet;

//Add table headers going cell by cell.
//oSheet.Cells[1, 1] = "First Name";
//oSheet.Cells[1, 2] = "Last Name";
//oSheet.Cells[1, 3] = "Full Name";
//oSheet.Cells[1, 4] = "Salary";

//Format A1:D1 as bold, vertical alignment = center.
//oSheet.get_Range("A1", "D1").Font.Bold = true;
//oSheet.get_Range("A1", "D1").VerticalAlignment =
//    Excel.XlVAlign.xlVAlignCenter;

//Fill A1:B20 with an array of values (First and Last Names).
oSheet.get_Range("B1", "C20").Value2 = citations;

////Fill C2:C6 with a relative formula (=A2 & " " & B2).
//oRng = oSheet.get_Range("C2", "C6");
//oRng.Formula = "=A2 & \" \" & B2";

////Fill D2:D6 with a formula(=RAND()*100000) and apply format.
//oRng = oSheet.get_Range("D2", "D6");
//oRng.Formula = "=RAND()*100000";
//oRng.NumberFormat = "$0.00";

////AutoFit columns A:D.
//oRng = oSheet.get_Range("A1", "D1");
//oRng.EntireColumn.AutoFit();

//Manipulate a variable number of columns for Quarterly Sales Data.
//DisplayQuarterlySales(oSheet);

//Make sure Excel is visible and give the user control
//of Microsoft Excel's lifetime.
oXL.Visible = true;
oXL.UserControl = true;
}
catch (Exception theException)
{
String errorMessage;
errorMessage = "Error: ";
errorMessage = String.Concat(errorMessage, theException.Message);
errorMessage = String.Concat(errorMessage, " Line: ");
errorMessage = String.Concat(errorMessage, theException.Source);

//MessageBox.Show(errorMessage, "Error");
}
}

public enum ResponseCategories
{
Unknown = 0,       // Unknown code ( < 100 or > 599)
Informational = 1, // Informational codes (100 >= 199)
Success = 2,       // Success codes (200 >= 299)
Redirected = 3,    // Redirection code (300 >= 399)
ClientError = 4,   // Client error code (400 >= 499)
ServerError = 5    // Server error code (500 >= 599)
}

public static string GetHtmlFromUrl(string url)
{
if (string.IsNullOrEmpty(url))
throw new ArgumentNullException("url", "Parameter is null or empty");

string html = "";
HttpWebRequest request = GenerateHttpWebRequest(url);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (VerifyResponse(response) == ResponseCategories.Success)
{
// Get the response stream.
Stream responseStream = response.GetResponseStream();
// Use a stream reader that understands UTF8.
using (StreamReader reader =
new StreamReader(responseStream, Encoding.UTF8))
{
html = reader.ReadToEnd();
}
}
}
return html;
}

public static HttpWebRequest GenerateHttpWebRequest(string UriString)
{
// Get a Uri object.
Uri Uri = new Uri(UriString);
// Create the initial request.
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(Uri);
// Return the request.
return httpRequest;
}

// POST overload
public static HttpWebRequest GenerateHttpWebRequest(string UriString,
string postData,
string contentType)
{
// Get a Uri object.
Uri Uri = new Uri(UriString);
// Create the initial request.
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(Uri);

// Get the bytes for the request; should be pre-escaped.
byte[] bytes = Encoding.UTF8.GetBytes(postData);

// Set the content type of the data being posted.
httpRequest.ContentType = contentType;
//"application/x-www-form-urlencoded"; for forms

// Set the content length of the string being posted.
httpRequest.ContentLength = postData.Length;

// Get the request stream and write the post data in.
using (Stream requestStream = httpRequest.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
// Return the request.
return httpRequest;
}

public static ResponseCategories VerifyResponse(HttpWebResponse httpResponse)
{
// Just in case there are more success codes defined in the future
// by HttpStatusCode, we will check here for the "success" ranges
// instead of using the HttpStatusCode enum as it overloads some
// values.
int statusCode = (int)httpResponse.StatusCode;
if ((statusCode >= 100) && (statusCode <= 199))
{
return ResponseCategories.Informational;
}
else if ((statusCode >= 200) && (statusCode <= 299))
{
return ResponseCategories.Success;
}
else if ((statusCode >= 300) && (statusCode <= 399))
{
return ResponseCategories.Redirected;
}
else if ((statusCode >= 400) && (statusCode <= 499))
{
return ResponseCategories.ClientError;
}
else if ((statusCode >= 500) && (statusCode <= 599))
{
return ResponseCategories.ServerError;
}
return ResponseCategories.Unknown;
}

Часть этих функций нужна, чтобы запросить HTML, часть чтобы очистить его от тэгов. Набор этих функций, как и код кнопки будут меняться в зависимости от того, с какого именно сайта вы хотите получить контент. То есть данный метод не универсален, его надо затачивать под каждый сайт. Я не буду подробно разъяснять этот код, так как все равно нужно обладать хорошими знаниями в C#, чтобы применять данный метод. Кроме этого, тут есть неплохие комментарии.

4. Здесь http://support.microsoft.com/kb/302084 описано, как писать код для загрузки данных в Excel.

5. Далее, как я описал ранее, можно выгрузить данные из Excel в XML, а XML уже загрузить туда, куда вам надо. Смотрите предыдущий пост в этом блоге.

Метод наполнения базы SQLite через выгрузку Excel данных в XML

Здесь будет описан метод, который позволяет наполнять базу данных SQLite из Excel посредством выгрузки данных в XML.

SQLite — легковесная встраиваемая реляционная база данных. Исходный код библиотеки передан в общественное достояние. В 2005 году проект получил награду Google-O’Reilly Open Source Awards. Простота и удобство встраивания SQLite привели к тому, что библиотека используется в браузерах, музыкальных плеерах и многих других программах. Многие программы поддерживают SQLite в качестве формата хранения данных (особенно в Mac OS и iPhone OS, Android).

Можно использовать Microsoft Excel 2007, на других версиях метод не тестировался. Предположим, есть заполненная данными таблица Excel 2007 с четырьмя столбцами: ID, Text, Author, Favorite.

1. Создаем XML файл в Windows – образец будущего большого XML файла. Он будет играть роль схемы в Excel. Например,

<?xml version=”1.0″ encoding=”UTF-8″ standalone=”yes”?>
<BusCits xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”>
<BusCit>
<ID>1</ID>
<Text>Т1</Text>
<Author>А1</Author>
<Favorite>N</Favorite>
</BusCit>
<BusCit>
<ID>2</ID>
<Text>Т2</Text>
<Author>А2</Author>
<Favorite>N</Favorite>
</BusCit>
</BusCits>

Здесь представлены два элемента BusCit, в каждом из которых есть параметры ID, Text, Author, Favorite. Элементы являются дочерними по отношению к главному элементу BusCits. Сохраняем этот образцовый XML. Назовем его XMLSchema.xml.

2. В Excel 2007 в Ribbon’е есть вкладка Разработчик. Открываем ее. На этой вкладке есть раздел XML. Нажимаем там на кнопку “Источик”, а затем в появившейся справа панели на кнопку “Карты XML…”. Нажимаем Добавить и добавляем ранее сохраненный XMLSchema.xml. Нажимаем Ок. Соглашаемся использовать маленький XML в качестве схемы. Дальше в той же правой панели Источник XML должна появиться ваша схема. Нажимаем правой кнопкой на ID и выбираем Сопоставить элемент. Далее выбираем первый столбец в таблице с ID, нажав на букву, которая его идентифицирует, при этом заголовки тоже выделяются(A, B, C и т.д). Аналогично поступаем с каждым другим параметром: Text, Author, Favorite.  Мы привязали XML схему к таблице, теперь во вкладке Разработчик/XML в Ribbon нажимаем Export и экспортируем XML с нужным нам названием, например BusCits.xml. Готово, получившийся XML можно удобно посмотреть в программе Notepad++ и проверить. Должно получиться что-то вроде этого:

3. Запускаем Mac Os X. Заходим в XCode и, используя сайт http://www.tbxml.co.uk и  библиотеку, описанную в нем, пишем код для парсинга XML файла. Можно использовать любую другую облегченную библиотеку XML.
Пример работающего кода:


-(void) insertBusCitsToDatabase {
// Setup the database object
sqlite3 *database;
char *sqlStatement;
NSString *insert;
//Подготовка к парсингу XML
TBXML * tbxml = [[TBXML tbxmlWithXMLFile:@"BusCits.xml"] retain];
//Получение корневого элемента
TBXMLElement * rootXMLElement = tbxml.rootXMLElement;
TBXMLElement * XMLBusCit;
TBXMLElement * XMLID;
TBXMLElement * XMLText;
TBXMLElement * XMLAuthor;
TBXMLElement * XMLFavorite;
NSString *BusCitText;
NSString *BusCitId;
NSString *BusCitAuthor;
NSString *BusCitFavorite;
char *errMsg;
int returnValue;

// Init the busCits Array
busCits = [[NSMutableArray alloc] init];

//Cycle until XML ended
//1. Read XML to busCit object
//2. Insert busCit object to DB
//End Cycle

// Open the database from the users filessytem
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {

XMLBusCit = [TBXML childElementNamed:@"BusCit" parentElement:rootXMLElement];
if (XMLBusCit==nil) {
return;
}

while (XMLBusCit) {

if (XMLBusCit==nil) {
break;
}
XMLID = [TBXML childElementNamed:@"ID" parentElement:XMLBusCit];
XMLText = [TBXML childElementNamed:@"Text" parentElement:XMLBusCit];
XMLAuthor = [TBXML childElementNamed:@"Author" parentElement:XMLBusCit];
XMLFavorite = [TBXML childElementNamed:@"Favorite" parentElement:XMLBusCit];
BusCitText = [TBXML textForElement:XMLText];
BusCitId = [TBXML textForElement:XMLID];
BusCitAuthor = [TBXML textForElement:XMLAuthor];
BusCitFavorite = [TBXML textForElement:XMLFavorite];

NSLog(BusCitId);
NSLog(BusCitText);
NSLog(BusCitAuthor);
NSLog(BusCitFavorite);
sqlite3_stmt *insertStatement;
char *st;

//Генерация и подготовка SQL выражения для вставки записи

insert = [[NSString alloc] initWithFormat:@"INSERT OR REPLACE INTO BusCits (ID, Text, Author, Favorite) VALUES ('%@', '%@', '%@', '%@');", BusCitId, BusCitText, BusCitAuthor, BusCitFavorite];
st = [insert UTF8String];
//NSLog(st);
returnValue = sqlite3_exec (database, st, NULL, NULL, &errMsg);
if (returnValue != SQLITE_OK)
{
NSLog(@"Addition failed");
//NSLog(errMsg);
}
else
{
NSLog(@"Addition Ok!");

}
XMLBusCit = XMLBusCit->nextSibling;
}

// Setup the SQL Statement and compile it for faster access
const char *sqlStatement = "SELECT * FROM BusCits";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK)
{
// Loop through the results and add them to the feeds array
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
// Read the data from the result row
NSString *aId = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
NSString *aText = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
NSString *aAuthor = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)];
NSString *aFavorite = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 4)];

// Create a new animal object with the data from the database
BusCit *busCit = [[BusCit alloc] initWithID:aId Text:aText Author:aAuthor Favorite:aFavorite];
// Add the animal object to the animals Array
[busCits addObject:busCit];

[busCit release];
}
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);

}
sqlite3_close(database);

}

Для того, чтобы посмотреть и проверить работу используется NSLog. После отработки функции можно нажать Shift+Command+R и вызвать консоль, в которой пишется то, что в NSLog.

О runtime ошибке SIGABRT

Баг с текстом SIGABRT в NSLog может появляться при тестировании программы на iPhone Simulator. Например, при открытии нового View. То есть он возникает во время работы программы, а компилятор XCode не находит эту ошибку. На понимание причины бага или сигнала SIGABRT было потрачено 3-4 часа. Поэтому было решено написать эту статью. Посмотрим сначала, что нам пишет википедия об этой ошибке.

POSIX® (англ. Portable Operating System Interface for Unix — Переносимый интерфейс операционных систем Unix) — набор стандартов, описывающих интерфейсы между операционной системой и прикладной программой. Стандарт создан для обеспечения совместимости различных UNIX-подобных операционных систем и переносимости прикладных программ на уровне исходного кода, но может быть использован и для не-Unix систем.
В POSIX-системах, SIGABRT — сигнал, посылаемый процессом самому себе при выполнении функции abort(), для аварийного останова, в случае невозможности дальнейшего продолжения программы. Сигнал SIGABRT процесс посылает сам себе, когда вызывает функцию abort() (функция libc, с прототипом в stdlib.h). Сигнал SIGABRT может быть перехвачен или проигнорирован, но abort() принудительно завершит программу (предварительно сбросив и закрыв стандартные потоки и сделав дамп памяти программы) даже если этого не сделает обработчик сигнала. Таким образом, функция abort() гарантирует завершение программы, почему она часто используется библиотеками в аварийных ситуациях — когда выполнение не должно быть продолжено, но основная программа должна иметь возможность выполнить действия, необходимые перед аварийным завершением. Также SIGABRT вызвается утверждениями (англ. assertions; средство отладки Си — макроопределение assert() вызывает abort() если утверждение переданное в качестве аргумента ложно).

Из этого текста можно понять, что ошибка или сигнал SIGABRT посылается просто из-за вызова функции abort() при падении программы. В свою очередь эта функция может вызываться утверждением assert(), но мы не можем посмотреть и выявить точную причину бага. Поэтому SIGABRT – один из самых вредных и труднопреодолимых багов при разработке для iPhone: отладка(debugging) не помогает, так как ошибка возникает где-то в коде, который не доступен разработчику. В интернете можно прочитать много всего про этот баг приложений для iPhone. Кому-то помогла перезагрузка XCode каким-то магическим образом или “Clean all Targets”. Пишут также, что это ошибка XCode или Симулятора, а не ошибка разработчика. Я думаю, что проблема в другом.

Наверное, главная и самая распространенная причина этой ошибки(касательно iPhone, iPhone Simulator) в том, что XIB не соответствует вашим аутлетам(Outlets) или классам. Например, если написать:
@interface FavoritesTableView : UITableViewController,

когда у вас нет контроллера TableViewController, а вместо него обычный View с контролом TableView, то выскочит эта ошибка. Видимо, программа пытается обратиться к сущностям, которых нет, при загрузке View. Они либо были освобождены из памяти(deallocated) раньше времени, либо их просто нет (например, в XIB). Далее вызывается abort(), который посылает сигнал SIGABRT.

Итак, в данном случае надо было написать:
@interface FavoritesTableView : UIViewController

Также SIGABRT может быть вызван обращением к любой несуществующей сущности – к элементу за пределами массива, к переменной, объекту, XIB файлу и т.д.