Как вывести данные из таблицы excel андроид студио котлин

Обновлено: 08.07.2024

Операции чтения и записи в файл являются стандартным функционалом любых приложений, которые ведут журналирование событий, работу с файлами, вплоть до передачи данных по сети. В данной статье рассмотрим методы записи в файлы информации и чтения из файла записанной строки.

Структура проекта

Эстетических изменений стандартных кнопок или ListView в данном уроке производиться не будет, поскольку мы будем работать с тем, что скрыто от глаз пользователя, а именно работать с файлами.

Вся структура проекта соответственно состоит на этот раз лишь из одного класса: MainActivity

Также в проекте присутствуют следующие файлы ресурсов:

  1. activity_main.xml
  2. strings.xml
  3. styles.xml - в данном файле отсутствуют какие-либо изменения относящиеся к проекту.

Кроме этого внесены изменения в файл AndroidManifest.xml. В файле необходимо добавить следующие две строки. Это разрешения для приложения - производить операции чтения и записи с внешним накопителем (то есть SD Card телефона) В современным смартфонах на базе ОС Android в большинстве случаев запись информации производится во внешний накопитель, хотя обычный пользователь считает этот накопитель внутренним, поскольку он является встроенным, но с точки зрения операционной систем данный накопитель (то есть SD Card) является внешним накопителем. В данной статье не будет рассматриваться вариант работы с истинно внутренним накопителем.

Формирование разметки приложения

activity_main.xml

Разметка основной активити, в которой будет производиться работа нашего приложения. В данной разметке присутствует всего две кнопки (Button) и текстовое поле (TextView), в которое мы будем выводить информацию сохранённую в файле.

strings.xml

Файл ресурсов текста в ОС Android. Подготовка всех строк, которые применяются в Вашем Приложении в данном файле, является не только хорошим тоном, но обязательным условием для разработки качественного Приложения. Поскольку, если вы будете дисциплинировать себя, сохранять всю подобную информацию в данном файле, то впоследствии это окупится, когда вы будете производить перевод Приложения на другие языки. Тем более, что в Android Studio имеется удобный функционал для этого.

styles.xml

В данном файле нет изменений относящихся к проекту. Но при создании проекта стандартная тема оформления не рендерится Android Studio. Выдается ошибки при предпросмотре и в режиме дизайна. Чтобы этого избежать, пропишите следующую информацию взамен старой.

Основной класс проекта - MainActivity.java

Сегодня в данном классе сконцентрирован весь программный код. В данном классе производится формирование внешнего вида главной активити, а также организуется работа с файлами.

Если в процессе изучения материала не возникло никаких проблем и ошибок, то по нажатию кнопки записи в файл произойдет создание нового файла и будет произведена запись строки "Hello World". При нажатии кнопки чтения будет выведена информация сохранённая в текстовом файле. Процесс показан на скриншотах ниже.

По нажатию кнопки производится запись в файл информации

Чтение из файла производится по нажатию соответствующей кнопки. При этом в TextView выводится текст

Всем привет! Идея для этой статьи пришла еще месяц назад, но в силу занятости на работе времени катастрофически не хватало. Однажды вечером в YouTube я наткнулся на ролик о создании игры-платформера в стиле пиксельной графики. И тут мне вспомнились мои первые уроки информатики в школе, где мы "рисовали на Бейсике" и играли в "ворона ест буквы".

Предисловие

На дворе стоял 2000-й год. Кризис 98 года остался позади. Я учился в 8 классе местной школы, в небольшом городке. С началом учебного года всех ждало небольшое событие - ввели урок информатики. Многие отнеслись к этому, как к еще одному предмету который надо учить, но были и те, у кого загорелись глаза. В числе последних оказался и я.

Надо отметить, что информатику хоть и ввели, но "ввести новые компьютеры" забыли, потому что денег на эти цели не было. На службе у нашей школы тогда стояли машины made in USSR - "Электроника МС 0511" и несколько их чуть более современных аналогов. Работали они только по им самим ведомым законам, или после прихода некоего "Николая Владимировича" - местного мастера.

фото с сайта - red-innovations.su

фото с сайта - red-innovations.su

Вести предмет как водится поставили молодого и "горячего" преподавателя - девушку 26 лет, которая кстати очень старалась. Мы учили системы счисления и переводили письменно числа из одной в другую. Читали про общее устройство ПК и конечно был Бейсик. У каждого тетрадка была в прочной прозрачной обложке, сзади которой была нарисована система координат. Это был своего рода холст для эскизов фигур, которые мы потом старательно переносили в код.

Именно эту тетрадь, с фигурами, нарисованными шариковой ручкой мне и напомнил ролик. Нахлынули воспоминания и захотелось сделать что-то похожее, пусть и без Бейсика, тем более что выдалась пара свободных вечеров.

Рисуем первое изображение

Для своих целей я взял BufferedImage. Начал с простой функции, которая рисует пиксель в заданных координатах и с определенным цветом.

Чтобы проверить работу набросал метод, который выводит картинку с пикселями рандомного цвета. В функции можно понизить значение каждого из каналов цвета, задав диапазон - красного redRng, зеленого greenRng и синего blueRng цвета.

Если поставить в цикле шаг stepSize отличный от единицы и занизить один из каналов, то можно получить интересный эффект.

рандомное изображение 1.) step 3, RGB (11, 238, 229) 2.) step 2, RGB (181, 19, 227)

рандомное изображение 1.) step 3, RGB (11, 238, 229) 2.) step 2, RGB (181, 19, 227)

Вроде что-то вырисовывается. Теперь надо сохранить результат. Роль по записи изображения была героически возложена на ImageIO. Насколько я знаю - он блокирующий, поэтому я его от греха подальше обернул в Thread.

Останавливаться на этом было глупо, поэтому следующим шагом решил сделать "рисовалку" на базе двумерного списка.

Пиксельное сердце

Координаты для отрисовки решил сделать в виде двумерного списка ArrayList<List<Int>>. Получить "пиксельный" эффект мне помогла функция drawTitle, которая "дергает" в цикле drawPixel, рисуя "big pixel" в виде плитки.

Настала очередь обработать массив с числами. Сказано-сделано. Добавив с помощью оператора when обработку 4 цветов…

…и создав список в виде двумерного массива, где каждая цифра соответствует своему цвету (1 = красный, 2 = темно-красный, 3 = белый, 4 = фиолетовый)

. на выходе получил такую красоту. Мой внутренний "школьник" был очень доволен.

pixel heart

pixel heart

И хотя все получилось как я ожидал, но "рисовать цифрами" то еще удовольствие, да и хотелось на выходе получать что-то посложнее в плане цвета и детализации, поэтому я задумался о визуальном редакторе. Но запасы чая таяли на глазах, а вечер постепенно перетекал в ночь, поэтому решено было отложить задачу до завтра.

Excel как холст

Следующим вечером я продолжил. Сперва подумал о JS (React JS), но тут нужно было переписывать все полностью на нем, да и JavaScript я пробовал слишком давно. Хотелось взять что-то простое…

По работе часто приходится работать с таблицами, поэтому само собой выбор остановился на Excel. Привел строки столбцы к виду квадратной сетки и вуаля - наш холст готов к работе с цифровыми красками. Осталось лишь только получить данные из ячеек. "Цифровая бумага все стерпит" - подумал я, и взял Apache POI - библиотеку для работы файлами word, excel, pdf. Документация у нее написана хорошо, но некоторые примеры кода там явно требуют корректировки.

Для начала набросал простую лямбду для преобразования hex в rgba, которая отдает стандартный джавовский класс Color.

Теперь оставалось пройтись по листу и собрать все ячейки в массив, попутно извлекая цвет у закрашенной ячейки и проставляя его в пустых.

Функция немаленькая и всю ее приводить я не буду (ссылка на код в конце статьи). Конечно, ее можно сократить, но ради читаемости я оставил все как есть. И тут хотелось бы остановиться на одном моменте.

Чтобы создать двумерный массив с пикселями, нужно узнать количество строк и столбцов, в которых есть закрашенные ячейки. И если следовать примеру из документации и сделать так.

Редактор пикселей в Excel

Редактор пикселей в Excel

Дело сталось за малым - преобразовать нашу "пиксельную матрицу" в картинку и вернуть в качестве результата BufferedImage. В отличии от начала статьи, тип картинки у нас изменился на - TYPE_INT_ARGB, чтобы не закрашенные ячейки таковыми и оставались.

Теперь, запасшись малиновым чаем и любимой музыкой можно придаться ностальгии и творить.

отрисованная картина в Excel. за основу взята работа Mockingjay1701

отрисованная картина в Excel. за основу взята работа Mockingjay1701

Выводы

Весь код доступен по ссылке на github. Что дальше? В планах добавить поддержку svg, может добавить несколько фильтров (blur, glitch, glow, etc..), переписать все с “индусского кода” на человеческий, добавить поддержку xls (HSSF Color) и возможно набросать пару тестов. Чего-то больше добавлять не имеет смысла, так как это скорее интересная задача с легким налетом ностальгии, чем какой-то проект.

Послесловие

Конечно, можно было ограничиться лишь "Фотошопом и Экселем" (ctrl+c, ctrl+v), но цель была не просто получить пиксельный "шедевр" в пару кликов. Хотелось вспомнить школьные уроки информатики, ту теплую атмосферу: Бейсик, старые компьютеры, пиксельные рисунки на экране черно-белого монитора "Электроника МС". Да черт побери, в конечном счете это хоть и простая, но интересная задача, потратить на которую пару вечеров просто приятно.

И раз уж текст скорее всего выйдет накануне 14 февраля, то пусть он будет своеобразным признанием в любви к технологиям, которыми я с того самого дня и по настоящее время увлечен.


Пусть через пару лет "Электронику МС" сменили современные аналоги на базе Pentium, те первые занятия на старых компьютерах навсегда останутся со мной, ведь именно они вложили в меня любовь к компьютерам и всему что с ними связано.

В этом уроке продолжим модифицировать наше приложение Расписания уроков для андроид устройств, и изменим принцип загрузки данных во фрагменты.

В предыдущей версии информация поступала из строковых массивов, которые были созданы в файле String.xml, посредником между данными и приложением являлся Array Adapter, а сегодня сделаем загрузку из базы данных SQLite.

Она будет находиться в apk файле, вместе с самим приложением, так что никаких настроек или манипуляций не нужно будет делать. Установил, открыл - работает.

Кто не читал статью "Создание расписания уроков для андроид устройств. Array Adapter для фрагментов" переходите по ссылке, в ней вы сможете скачать файл проекта, который будем редактировать.

Создание базы данных в Excel

В прошлой статье я не оговорился, сказав, что базу данных будем делать в Excel. Давайте создадим таблицу с расписанием уроков, по классам, дням недели и перечнем занятий.
Для этого в новой книге дадим названия полей таблицы:

  • class - номер класса(11-6)
  • day - день недели(1-5)
  • urok_id- порядок уроков
  • urok - название предмета.

На втором листе книги напишем номер предмета и название, с помощью функции на первом листе в столбец urok введем формулу =СЛУЧМЕЖДУ(1;13) так как на втором листе 13 предметов, а в соседнюю ячейку =ВПР(D2,Лист2!A:B;2;0) для получения списка пердметов.

Использование DB Browser for SQLite

Затем скопируем как значения получившийся список на новый лист и сохраним его как CSV(разделитель - запятые).

Далее нам понадобится программа DB Browser for SQLite (я пользуюсь версией 3.5.1), в которой создадим новую базу данных(New Database), назавем ее 1.sqlite.

Нажмем File->Import->Table from CSV file. укажем путь к сохраненной ранее книге, присвоим название таблице myrasp, поставим галочку Column name in first line, кодировка Other - CP1251, разделитель ";" и нажмем Ok.

Модифицируем таблицу myrasp, нажав ПКМ, добавим новое поле(Add field) "_id" с типом text или integer, отметим галочками PK(первичный ключ) и AI(автоинкремент). Поле "_id" можно поднять выше в списке полей таблицы.

Создание директории assets

Вернемся в Android Studio и создадим папку assets для хранения нашей базы данных SQLite, нажав в проекте ПКМ: New->Folder->Asset Folder. Если вы скопируете 1.sqlite то можно сразу в эту папку вставить файл, я же в Total Comander переименую в rasp.sqlite и скопирую в проект в папку assets. Когда мы перейдем в среду разработки Android Studio, то в папке будет видна наша база.

Изменения не коснутся файлов MainActivity.java и MainActivity11.java, будем использовать код из предыдущего проекта. В файле fragment_main11.java, отвечающем за отображение уроков понедельника уберем конструкцию switch(classId)<> целиком, удалим переменную ListAdapter adapter.

Класс DatabaseHelper.java для работы с базой данных

Создадим новый класс DatabaseHelper.java, он понадобится для связи с базой данных, открытия, чтения данных.

Данный код универсален для любых проектов, в настройках можно менять названия переменных DB_NAME, TABLE, COLUMN_.

Настройки таблицы

Напишем название базы данных и таблицы в переменные

Присвоим поля таблицы myrasp переменным

Хочу обратить ваше внимание на переменную DB_PATH, которую я для упрощения написал просто "/data/data/"+название пакета+"/database/". В моем случае название пакета - ru.maxfad.myraspisanie, у вас может и будет отличаться для других приложений.

Работа с фрагментами

Теперь откроем fragment_main11.java, в который добавим метод onCreateView

Поскольку нам нужно получить доступ к фрагменту из активности напишем функцию, в которой свяжемся со слоем фрагмента fragment_main11.xml, а в переменную mList получим ListView для отображения уроков

Во fragment_main11.xml удалим секцию разметки TextView и переименуем id ListView

Добавим переменные для работы с базой данных

В метод onActivityCreate напишем новый экземпляр класса DatabaseHelper и создадим базу данных

Напишем метод onResume в котором и будет происходить выборка данных из таблицы myrasp, выполняться SQL запрос и формироваться список уроков

Как вы можете обратить внимание, в строке " and day=1" и заключается принцип загрузки данных по дням недели, в остальных фрагментах код будет отличаться только номером дня.

При запуске приложения в эмуляторе по нажатию на кнопку в фрагменты будет грузиться информация о расписании уроков, происходит деление по дням недели.

Архив с кодом проекта можно скачать по ссылке ниже, обязательно посмотрите видеоролик по материалам статьи, в нем есть БОНУС: на примере этого приложения я покажу, как работать в Android Studio с макетом с помощью BluePrint+Design.

А на сегодня все, делитесь этой статьей в соцсетях и подписывайтесь на канал YouTube.

Cкачать архив для ознакомления - проект Расписание для уроков:

Создание расписания уроков для андроид устройств. Часть 2. База данных SQLITE и фрагменты + БОНУС :

Рекомендуем смотреть видео в полноэкранном режиме, в настойках качества выбирайте 1080 HD, не забывайте подписываться на канал в YouTube, там Вы найдете много интересного видео, которое выходит достаточно часто. Приятного просмотра!

В этой статье мы узнаем, как сохранять данные в Kotlin с помощью JDBC (Java Database Connectivity).

Пример проекта

В качестве примера я буду использовать Bytebank, проект, имитирующий цифровой банк, для регистрации счетов. Для регистрации счета требуется номер счета, имя клиента и баланс:

В классе Account мы представляем наш счет, который может быть создан следующим образом:

И к этому результату мы пришли, запустив программу:

После представления проекта и создания учетной записи давайте приступим к настройке JDBC.

Добавление коннектора базы данных MySQL

В качестве первого шага нам необходимо создать соединение между нашим приложением и базой данных.

В этом примере я буду использовать MySQL, но можно установить такое же соединение и с другими распространенными базами данных на рынке, поскольку каждая из них предлагает коннектор, способный осуществлять связь.

MySQL, например, имеет специальную страницу со всеми доступными драйверами, даже из других приложений.

На странице MySQL у нас есть возможность загрузить коннектор, однако, учитывая использование инструмента сборки (Gradle), мы можем добавить зависимость в файл сборки, build.gradle.kts:

Далее нам просто нужно синхронизировать проект, чтобы Gradle загрузил и сделал драйвер доступным для использования. Затем мы можем приступить к настройке соединения.

Создание подключения

Когда драйвер доступен, мы можем создать соединение с MySQL следующим образом:

У нас здесь много кода! Не пугайтесь, потому что мы будем разбираться, что означает каждая строчка кода:

В этом вызове нам нужно обратить внимание в основном на адрес! Например, у нас по умолчанию стоит jdbc:mysql, что указывает на то, что мы будем устанавливать соединение JDBC с базой данных MySQL, т.е. если вы делаете конфигурацию для другой базы данных, то значение будет другим!

Примечание: еще один момент, который следует отметить, заключается в том, что я использую базу данных на своем компьютере, на порту 3306 (порт MySQL по умолчанию), поэтому достаточно localhost. Однако при интеграции с внешней базой данных адрес будет другим!

Обратите также внимание, что мы указываем базу данных, к которой хотим получить доступ, и в данном случае я создал банк bytebank. Не стесняйтесь использовать этот же пример или другой по вашему выбору.

После ввода каждой строки кода, при запуске программы мы получаем следующий результат:

Вот и все! Мы можем начать выполнение операторов в MySQL.

Создание таблиц

Из всех возможностей, нашим первым действием с MySQL будет создание таблицы, в которой будет храниться информация о счете! Для этого рассмотрим следующий оператор SQL:

Чтобы создать запрос, нам нужно обернуть весь оператор в строку (мы можем использовать строковый литерал или необработанную строку).

Затем нам нужно подготовить наш запрос из метода prepareStatement() соединения и выполнить его с помощью execute():

При запуске программы мы получаем следующий результат в консоли:

У нас есть наша таблица! Теперь мы можем вносить счета в базу данных!

Внесение счетов

Чтобы вставить счет в таблицу, сначала мы выполняем шаги, аналогичные тем, что мы делали для создания таблицы, объявляем и подготавливаем запрос, а затем выполняем:

Большая разница заключается в том, что нам нужно выполнить процесс связывания, чтобы связать данные нашего объекта с запросом. Для этого мы используем сеттеры PrepareStatement:

Довольно часто возникают подобные сомнения, чтобы увидеть это решение, когда мы используем технику связывания данных, чтобы избежать проблем безопасности, таких как SQL Injection. Обратите внимание, что в этой технике мы используем значение 1 для функции setString(), которая получает клиента в качестве аргумента, и значение 2 для функции setDouble(), которая получает баланс.

После выполнения процесса связывания мы можем запустить программу, однако важно закомментировать или удалить код создания таблицы, поскольку в противном случае мы получим следующее исключение:

Обратите внимание, что это java.sql.SQLSyntaxErrorException, указывающий на то, что таблица счетов уже была создана… Мы можем использовать некоторые приемы, чтобы избежать этой проблемы, например, использовать if в операторе создания таблицы:

При повторном тестировании программы наш счет вставляется в таблицу:

Мы даже можем проверить результат непосредственно в MySQL:

Теперь, когда мы научились сохранять учетные записи, мы можем приступить к реализации поиска учетных записей.

Поиск счетов

Для получения счетов мы выполняем ту же процедуру, но разница в том, что теперь мы используем функцию executeQuery(), которая возвращает ResultSet, представляющий собой таблицу базы данных в соответствии с выполненным запросом.

Чтобы получить каждый счет, нам нужно просмотреть каждую строку ResultSet, мы можем сделать это с помощью метода next(), который переходит к следующей строке ResultSet и возвращает true, если есть данные, или false, если нет:

Таким образом, для каждой строки мы можем получить значение столбцов из геттеров, например, в первом столбце, который представляет id типа Int, мы используем getInt() с аргументом 1, указывающим на первый столбец, во втором мы используем getString() с аргументом 2, чтобы получить второй столбец, который является клиентом, и так далее…

Перед запуском программы мы можем даже сохранить новую учетную запись, если результат показывает более одной учетной записи:

Обратите внимание, что даже при номере счета 1, на счете Владимир он был записан со значением 2. Это происходит из-за того, что в процессе привязки не передается номер счета и сохраняется настройка автоматического увеличения в таблице.

Одна из проблем с JDBC

Особенностью этого решения является то, что нам необходимо точно знать тип значения, которое мы хотим получить для каждого столбца, потому что если мы выполним getInt(), а значением столбца будет текст (строка), у нас возникнет исключение при преобразовании:

Вы можете сделать эту имитацию, попытавшись получить столбец customer, как если бы это было целое число val test = result.getInt(2).

Это одна из проблем JDBC. Обратите внимание, что он показывает исключение NumberFormatException, указывающее на строковую запись со значением Алексей.

Заключение

Как представлено в этой статье, мы можем использовать те же решения на Java с помощью Kotlin. Если вы имели дело с JDBC, вы, вероятно, не заметили большой разницы с реализацией в Java, потому что в Kotlin мы можем изучить всю концепцию взаимодействия с Java, что позволяет использовать библиотеки Java в Kotlin! Это означает, что вы можете пойти дальше и даже использовать JPA, например, с Hibernate.

Читайте также: