Ошибка во время парсинга excel файла что это значит

Как исправить ошибку (парсим xls)?

Добрый день! Есть задача распарсить xls. Все вроде хорошо и не раз уже такое делал , пользуюсь библиотекой apache.poi .
Три строчки кода

И тут выпадает эксепшен:
«Exception in thread «main» java.lang.RuntimeException: Unexpected missing row when some rows already present»

Я примерно понимаю в что xls необычный и есть вырезанные ячейки, совмещенные ячейки/строки, но не понимаю как побороть данную ошибку.

  • Вопрос задан более трёх лет назад
  • 552 просмотра

ну а как обычно борят? Джава же данные не родит, если их там нет

отсеивайте проблемные строки, разбирайте вручную

Обычно . хм . наверное хияк-хияк )

А что значит проблемная строка ?

Полный эксепшен
Exception in thread «main» java.lang.RuntimeException: Unexpected missing row when some rows already present
at org.apache.poi.hssf.usermodel.HSSFSheet.setPropertiesFromSheet(HSSFSheet.java:211)
at org.apache.poi.hssf.usermodel.HSSFSheet.(HSSFSheet.java:136)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.(HSSFWorkbook.java:355)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.(HSSFWorkbook.java:400)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.(HSSFWorkbook.java:381)
at odsPars.main(odsPars.java:10)

Он указывает что ошибка в этой строке
HSSFWorkbook xlsxFile = new HSSFWorkbook(new FileInputStream(«../отчет.xls»));

Источник

Ошибка во время парсинга excel файла что это значит

Itsys
Дата 13.3.2008, 13:34 (ссылка) | (нет голосов) Загрузка .

Эксперт

Профиль
Группа: Завсегдатай
Сообщений: 1338
Регистрация: 21.1.2008
Где: г. Москва

Репутация: 1
Всего: 34

Требуется импортировать данные из Excel файлов в таблицу MS SQL
В SQL таблица состоит из колонок Col1, Col2 . Col30 тип ntext

Надо сделать импорт в эту таблицу произвольного Excel файла (структура может меняться, т.е. набор и количество колонок не постоянно) определенных колонок, т.е. не все подряд, а только допустим 3, 4 и 12 в соответствующие колонки таблицы MS SQL, т.е. 3 колонка в Col3, 4 в Col4, 12 в Col12 и начиная с определенной строки, например с 20 и до конца.

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

Второе больше не усложнение, а условие — файл Excel находится на другом сервере в сети и доступен через шару.

PS Данный механизм реализован на Perl, т.е. perl парсит Excel файл и с помошью запросов вставляет это в таблицу, но работает все это очень медлено файл Excel на 16000 строк и 20 колонок парсится около 1-2 минут. Загрузка процессора под 100%, весь отжирается памяти примерно вес файла *3 и загружается сеть, т.к. perl стоит там же, где лежит Excel — на другом сервере. Загрузку файла на 50000 строк, я так и не дождался — обрубил.

ЗЫ Самый главный вопрос, если это реализовать средствами MS SQL, если это, конечно, впринципе возможно, будет ли это работать быстрее и меньше грузить процессор, память и сеть?

Советчик

Профиль
Группа: Модератор
Сообщений: 20507
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 25
Всего: 453

О(б)суждение моих действий — в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция — Администрация форума.

Akina
Дата 13.3.2008, 13:42 (ссылка) | (нет голосов) Загрузка .

Опытный

Профиль
Группа: Участник
Сообщений: 418
Регистрация: 23.1.2008
Где: Московская област ь

Репутация: 10
Всего: 17

Magnifico
Дата 13.3.2008, 14:04 (ссылка) | (нет голосов) Загрузка .
Код
Select * From
Openrowset(‘msdasql’,’DRIVER=;ReadOnly=1;DefaultDir=c:\files\names.xls’,
‘Select * From [sheet1$]’)

Шустрый

Профиль
Группа: Участник
Сообщений: 125
Регистрация: 25.6.2007
Где: UA

Репутация: 2
Всего: 5

SharedNoob
Дата 13.3.2008, 14:52 (ссылка) | (нет голосов) Загрузка .
Itsys
Дата 13.3.2008, 15:06 (ссылка) | (нет голосов) Загрузка .

Эксперт

Профиль
Группа: Завсегдатай
Сообщений: 1338
Регистрация: 21.1.2008
Где: г. Москва

Репутация: 1
Всего: 34

Цитата(Akina @ 13.3.2008, 13:42 )
А почему не реализовать это собсно средствами VBA? прямо из модулёчка в самом этом Эксельном файле?
Или, например, промежуточная ADP-шка.

Потому-что это используется в интернет-магазине, написанном на perl, а файл Excel — это прайсы поставщиков, которые загружаются, сверяются с существующими товарами поставщика, корректируются цены и д.р. параметры товаров в магазине и добавляются новые — нет возможности добавить в Excel доп обработчики, т.к. файлы не наши, и обяснять как это делать каждому менеджеру после получения файла, собственно говоря не хочется

Цитата(Magnifico @ 13.3.2008, 14:04 )
для 2005 open rowset

У нас 2000 и пока никаких причин, чтобы покупать 2005 нет, хотя это может стать причиной, вопрос в скорости работы. насколько быстро данный запрос откроет файл на 10 мегов?

Добавлено через 2 минуты и 2 секунды

Цитата(SharedNoob @ 13.3.2008, 14:52 )
А собственно ДТС пакет не выход

Вообще не выход, т.к.

Цитата(Itsys @ 13.3.2008, 13:34 )
Надо сделать импорт в эту таблицу произвольного Excel файла (структура может меняться, т.е. набор и количество колонок не постоянно) определенных колонок, т.е. не все подряд, а только допустим 3, 4 и 12 в соответствующие колонки таблицы MS SQL, т.е. 3 колонка в Col3, 4 в Col4, 12 в Col12 и начиная с определенной строки, например с 20 и до конца.

Какие колонки импортировать а какие нет — определяет менеджер при импорте, и файлы у всех поставщиков очень уж разные

Опытный

Профиль
Группа: Участник
Сообщений: 418
Регистрация: 23.1.2008
Где: Московская област ь

Репутация: 10
Всего: 17

Magnifico
Дата 13.3.2008, 15:16 (ссылка) | (нет голосов) Загрузка .

Шустрый

Профиль
Группа: Участник
Сообщений: 125
Регистрация: 25.6.2007
Где: UA

Репутация: 2
Всего: 5

SharedNoob
Дата 13.3.2008, 15:17 (ссылка) | (нет голосов) Загрузка .
Цитата(Magnifico @ 13.3.2008, 14:04)
для 2005 open rowset
Код
Select * From
Openrowset(‘msdasql’,’DRIVER=;ReadOnly=1;DefaultDir=c:\files\names.xls’,
‘Select * From [sheet1$]’)

Дык а чем не устраивает это ? возвращает набор данных который лежит в ексель файле . да дальше вороти-нехачу .

Добавлено @ 15:18
ой извеняюсь, недочитал . sql2005

ДЛЯ SQL 2000
вариант 1

Код
SELECT *
FROM OPENDATASOURCE(
‘Microsoft Excel Driver (*.xls)’,
‘Data Source=D:\ ;’
). [название файлла без расширения]
Код
SELECT *
FROM OPENROWSET (‘MSDASQL’,
‘Driver=;
SourceDB=d:\;
DefaultDir=d:\;
SourceType=XLS;
Exclusive=No;
BackgroundFetch=Yes;
Collate=Russian;
Null=No;
Deleted=No;’,
‘SELECT * FROM [название файлла без расширения]’)

код на работоспособность не проверял но с драйвером для DBF все пашет

Это сообщение отредактировал(а) SharedNoob — 13.3.2008, 15:27

Itsys
Дата 13.3.2008, 15:41 (ссылка) | (нет голосов) Загрузка .

Эксперт

Профиль
Группа: Завсегдатай
Сообщений: 1338
Регистрация: 21.1.2008
Где: г. Москва

Репутация: 1
Всего: 34

А DefaultDir можно задать как \\server\files\?

Это сообщение отредактировал(а) Itsys — 13.3.2008, 15:42

Шустрый

Профиль
Группа: Участник
Сообщений: 125
Регистрация: 25.6.2007
Где: UA

Репутация: 2
Всего: 5

QA => F1 => поиск по указателю => OPENDATASOURCE (или OPENROWSET) => enter
и читаем.

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

Это сообщение отредактировал(а) SharedNoob — 13.3.2008, 15:54

SharedNoob
Дата 13.3.2008, 15:53 (ссылка) | (нет голосов) Загрузка .
Itsys
Дата 13.3.2008, 16:09 (ссылка) | (нет голосов) Загрузка .

Эксперт

Профиль
Группа: Завсегдатай
Сообщений: 1338
Регистрация: 21.1.2008
Где: г. Москва

Репутация: 1
Всего: 34

Цитата(SharedNoob @ 13.3.2008, 15:53 )
QA => F1 => поиск по указателю => OPENDATASOURCE (или OPENROWSET) => enter

До этого я сам догадался . Спасибо что напомнил, что есть такая функция в MS SQL (шутка). Ладно протестирую сообщу результаты.

Это сообщение отредактировал(а) Itsys — 13.3.2008, 16:09

Itsys
Дата 16.3.2008, 12:17 (ссылка) | (нет голосов) Загрузка .

Эксперт

Профиль
Группа: Завсегдатай
Сообщений: 1338
Регистрация: 21.1.2008
Где: г. Москва

Репутация: 1
Всего: 34

Код
SELECT TOP 10 * FROM OPENROWSET(
‘MSDASQL’,
‘Driver=Microsoft Excel Driver (*.xls);DBQ=\\pavlov\Files\34’,
‘SELECT * FROM [LIST$]’
) as xls

Только парсит он не правильно
В файле Excel строка:

Код
New NUM CISBN IDNAME CLARICHEV C_SERIE CNAME CAUTHOR CLONGNAME IINPACK IPAGETOTAL CFORMAT CCOVER cSizes1 iWeight1 YPRICE CPARTITION CSUBPRTION CPUBLNAME CEAN cComplete
Код
New NULL CISBN NULL NULL C_SERIE CNAME CAUTHOR CLONGNAME NULL NULL CFORMAT CCOVER cSizes1 NULL NULL CPARTITION CSUBPRTION CPUBLNAME CEAN cComplete

Почему некоторые значения изменены на NULL?

Опытный

Профиль
Группа: Участник
Сообщений: 418
Регистрация: 23.1.2008
Где: Московская област ь

Репутация: 10
Всего: 17

Могут разные тиы данных в одном столбце:
1
2
3
4
5
6

7A это потенциальный нулл — ошибка преобразования

если не принципиальны типы данных: приводить столбцы эксель к строке

Magnifico
Дата 16.3.2008, 14:51 (ссылка) | (нет голосов) Загрузка .
Код
Sub ПривестиКСтроке()
Dim temp As String
Dim str As String
str = «‘»
For Each c In Selection
temp = Trim(c.Value)

c.Value = str & temp
Next c
End Sub

Itsys
Дата 16.3.2008, 22:11 (ссылка) | (нет голосов) Загрузка .

Эксперт

Профиль
Группа: Завсегдатай
Сообщений: 1338
Регистрация: 21.1.2008
Где: г. Москва

Репутация: 1
Всего: 34

Цитата(Itsys @ 13.3.2008, 15:06 )
Потому-что это используется в интернет-магазине, написанном на perl, а файл Excel — это прайсы поставщиков, которые загружаются, сверяются с существующими товарами поставщика, корректируются цены и д.р. параметры товаров в магазине и добавляются новые — нет возможности добавить в Excel доп обработчики, т.к. файлы не наши, и обяснять как это делать каждому менеджеру после получения файла, собственно говоря не хочется

Есть друие предложения и варианты?

PS хотелось бы сделать все без вмешательства пользователей — получил файл по почте — загрузил в back-office интернет-магазина и все — дальше система сама все обрабатывет, менеджеру надо только подтверждать выполнение определнных действий..

Опытный

Профиль
Группа: Участник
Сообщений: 418
Регистрация: 23.1.2008
Где: Московская област ь

Репутация: 10
Всего: 17

попробуй с cast(ПОЛЕ as nvarchar(255)) поиграться

Magnifico
Дата 17.3.2008, 18:48 (ссылка) | (нет голосов) Загрузка .
Код
select [ЗДЕСЬ] from openrowset(
‘MSDASQL’,
‘Driver=Microsoft Excel Driver (*.xls);DBQ=\\pavlov\Files\34’,
‘SELECT [ИЛИ ЗДЕСЬ] FROM [LIST$]’
) as xls

если использовать эксель в качестве источника данных ADO ,OLE то полюбому будет приводится столбец к определенному типу данных
(которых больше в столбце) и будут ошибки преобразования.
Только банально перебирать столбцы и строки и приводить каждую ячейку к определн формату

для обработки грязных юзерских данных может и понадобится сложные обработчики писать и не в SQLSERVERE
да и ресурсоемкое это занятие

Itsys
Дата 17.3.2008, 21:21 (ссылка) | (нет голосов) Загрузка .

Эксперт

Профиль
Группа: Завсегдатай
Сообщений: 1338
Регистрация: 21.1.2008
Где: г. Москва

Репутация: 1
Всего: 34

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

Есть ли способ CASTить все поля запроса в VARCHAR без их конкретного указания, ну типа CAST(* AS VARCHAR(5000))?

Beltar
Дата 18.3.2008, 08:42 (ссылка) | (нет голосов) Загрузка .

Опытный

Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: нет
Всего: 7

Опытный

Профиль
Группа: Участник
Сообщений: 418
Регистрация: 23.1.2008
Где: Московская област ь

Репутация: 10
Всего: 17

есть еще опции HDR=Yes;IMEX=1;

«HDR=Yes; считает первую строку заголовком полей
«IMEX=1;» интерпретирует данные как текст

Magnifico
Дата 18.3.2008, 16:27 (ссылка) | (нет голосов) Загрузка .

Опытный

Профиль
Группа: Участник
Сообщений: 418
Регистрация: 23.1.2008
Где: Московская област ь

Репутация: 10
Всего: 17

используй лучше оле дб он покорректней работает

Magnifico
Дата 18.3.2008, 17:54 (ссылка) | (нет голосов) Загрузка .
Код
select *
from openrowset(‘Microsoft.Jet.OLEDB.4.0’
, ‘Excel 8.0; HDR=YES; IMEX=1;Database=C:\my.xls’
, [sheet1$])

Select *
FROM OPENDATASOURCE(‘Microsoft.Jet.OLEDB.4.0’, ‘Data Source=C:\my.xls;
Extended Properties=»Excel 8.0;HDR=Yes;»‘). [sheet1$]

Itsys
Дата 18.3.2008, 20:50 (ссылка) | (нет голосов) Загрузка .

Эксперт

Профиль
Группа: Завсегдатай
Сообщений: 1338
Регистрация: 21.1.2008
Где: г. Москва

Репутация: 1
Всего: 34

Beltar, Обработка на perl уже написана, толь проблема в том, что грузится очень долго, вот и ищу возможность быстрее обработать данные.

Itsys
Дата 19.3.2008, 00:24 (ссылка) | (нет голосов) Загрузка .

Эксперт

Профиль
Группа: Завсегдатай
Сообщений: 1338
Регистрация: 21.1.2008
Где: г. Москва

Репутация: 1
Всего: 34

Опытный

Профиль
Группа: Участник
Сообщений: 418
Регистрация: 23.1.2008
Где: Московская област ь

Репутация: 10
Всего: 17

Magnifico
Дата 19.3.2008, 11:44 (ссылка) | (нет голосов) Загрузка .
Код
Sub ПеребратьИменаЛистов()
Dim XLSFile As String
Dim i As Integer
i = 1
XLSFile = «C:\files\namesw.xls»

Dim ws As Worksheet
For Each ws In Worksheets

MsgBox «Имя » & i & » -го листа: » & ws.Name

Debug.Print «Имя » & i & » -го листа: » & ws.Name
i = i + 1
Next ws
End Sub

Itsys
Дата 19.3.2008, 14:30 (ссылка) | (нет голосов) Загрузка .

Эксперт

Профиль
Группа: Завсегдатай
Сообщений: 1338
Регистрация: 21.1.2008
Где: г. Москва

Репутация: 1
Всего: 34

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

Код
select *
from openrowset(‘Microsoft.Jet.OLEDB.4.0’
, ‘Excel 8.0; HDR=YES; IMEX=1;Database=C:\my.xls’
, [1])
Код
select *
from openrowset(‘Microsoft.Jet.OLEDB.4.0’
, ‘Excel 8.0; HDR=YES; IMEX=1;Database=C:\my.xls’
, [sheet[1]$])

Опытный

Профиль
Группа: Участник
Сообщений: 418
Регистрация: 23.1.2008
Где: Московская област ь

Репутация: 10
Всего: 17

Magnifico
Дата 19.3.2008, 20:49 (ссылка) | (нет голосов) Загрузка .
Цитата
Вопрос только в том, как это запустить

excel -> (alt + F11)(Редактор VB) — > insert ->module ->копироватьКодСюда ->правим пути в коде ->RUN

Ole automation это единственный способ добраться к свойствам и методам Эксель
Все языки программирования интегрируются с Эксель именно так, (и ничего другого кроме вышеприведенного кода не придумаешь)

Никаким запросом имена листов узнать невозможно
Эксель не база данных ,и нет возможности получить Информационную схему

Цитата
желательно в запрос передать

Если хочешь помучиться в 2000 есть расширенные хранимые процедуры на c++ (Visual Studio 6 )
(у меня на с++ «аллергия»)

В БОЛЕ набрать OLE Automation там есть какие то методы работы , можно вызывать VBA методы и св-ва (не разбирался)
ищи хороший пример

Или писать прогу на любом языке ,опять же интеграция с Эксель(код вверху)
подключение к sql server -> передача параметров из встроенного VBA в хранимую процедуру (с openrowsetoM)

Цитата
мне надо выбирать данные из первого листа в файле
Itsys
Дата 19.3.2008, 21:36 (ссылка) | (нет голосов) Загрузка .

Эксперт

Профиль
Группа: Завсегдатай
Сообщений: 1338
Регистрация: 21.1.2008
Где: г. Москва

Репутация: 1
Всего: 34

В общем решил я отказаться от этой затеи, т.к. срорее всего никакого убыстрения по сравнению с существующей обработкой на Perl я не получу.

Еще раз спасибо.

Опытный

Профиль
Группа: Участник
Сообщений: 418
Регистрация: 23.1.2008
Где: Московская област ь

Репутация: 10
Всего: 17

в 2005 это работает:

Magnifico
Дата 19.3.2008, 23:11 (ссылка) | (нет голосов) Загрузка .
Код
declare @file_name varchar(255), @h_application int, @hr int,@h_workbook int ,
@data varchar(255),@source varchar(255),@description varchar(255)

set @file_name = ‘c:\files\serge.xls’

exec @hr = sp_OACreate ‘Excel.Application’, @h_application OUT

exec @hr = sp_OAMethod @h_application, ‘Application.workbooks.Open’, @h_workbook OUT , @file_name
exec @hr = sp_OAGetProperty @h_application, ‘Workbooks(1).Sheets(1).Name’, @data OUT

SELECT @data as [dat]
exec sp_OAMethod @h_application, ‘Quit’
exec @hr=sp_OADestroy @h_application

—set @data =’NewSheet1′;

declare @SQL nvarchar(4000)
set @SQL =
‘SELECT * FROM OPENROWSET(»Microsoft.Jet.OLEDB.4.0»’ +’,’+»’Excel 8.0;HDR=Yes;IMEX=1;Database=C:\files\serge.xls»’+’,’+ »’Select * From [‘+ @data +’$]»)’

Itsys
Дата 19.3.2008, 23:55 (ссылка) | (нет голосов) Загрузка .

Эксперт

Профиль
Группа: Завсегдатай
Сообщений: 1338
Регистрация: 21.1.2008
Где: г. Москва

Репутация: 1
Всего: 34

Код
[quote=Magnifico, 19.3.2008, 23:11, post1447877]declare @file_name varchar(255), @h_application int, @hr int,@h_workbook int ,
@data varchar(255),@source varchar(255),@description varchar(255)

set @file_name = ‘c:\files\serge.xls’

exec @hr = sp_OACreate ‘Excel.Application’, @h_application OUT

exec @hr = sp_OAMethod @h_application, ‘Application.workbooks.Open’, @h_workbook OUT , @file_name
exec @hr = sp_OAGetProperty @h_application, ‘Workbooks(1).Sheets(1).Name’, @data OUT

SELECT @data as [dat]
exec sp_OAMethod @h_application, ‘Quit’
exec @hr=sp_OADestroy @h_applicatio[/quote]

Насколько я понимаю, это все работает не очень быстро

Опытный

Профиль
Группа: Участник
Сообщений: 418
Регистрация: 23.1.2008
Где: Московская област ь

Репутация: 10
Всего: 17

Это работает мгновенно!
Получить имя первого листа первой открытой книги- какая же здесь может быть нагрузка

Magnifico
Дата 20.3.2008, 09:27 (ссылка) | (нет голосов) Загрузка .
Код
exec @hr = sp_OAGetProperty @h_application, ‘Workbooks(1).Sheets(1).Name’, @data OUT

я просто незнаю будет ли работать в 2000?

Что то ты рано сдался! Это то что доктор прописал .

Одна тонкость Workbooks(1).Sheets(1).Name -мы получаем имя первого листа первой открытой книги,если будет открыта другая книга,
допустим локально , а потом будет выполнен этот запрос -то подхватит именно эту книгу ,а

Код
exec @hr = sp_OAMethod @h_application, ‘Application.workbooks.Open’, @h_workbook OUT , @file_name

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

Код
Workbooks(«Names.xls»).Sheets(1).Name

в 2000 OLE Automation должно как то включаться (поиск)

Itsys
Дата 20.3.2008, 17:41 (ссылка) | (нет голосов) Загрузка .

Эксперт

Профиль
Группа: Завсегдатай
Сообщений: 1338
Регистрация: 21.1.2008
Где: г. Москва

Репутация: 1
Всего: 34

Публиковать ссылки и обсуждать взлом чего бы то ни было.

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы составления неспецифических запросов рассматриваются здесь
  • Используйте теги [code=sql][/code] для подсветки кода. Используйтe чекбокс «транслит» (возле кнопок кодов) если у Вас нет русских шрифтов.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Zloxa, Akina.

0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | MS SQL Server | Следующая тема »

[ Время генерации скрипта: 0.2007 ] [ Использовано запросов: 21 ] [ GZIP включён ]

Источник

Читайте также:  Аметропия что это значит
Оцените статью